欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python實(shí)現(xiàn)CSV文件編碼轉(zhuǎn)換工具(轉(zhuǎn)成UTF-8格式)

 更新時(shí)間:2025年08月26日 10:05:52   作者:小莊-Python辦公  
這篇文章主要為大家詳細(xì)介紹了如何使用Python實(shí)現(xiàn)CSV文件編碼轉(zhuǎn)換工具,即轉(zhuǎn)成UTF-8格式,文中的示例代碼講解詳細(xì)感興趣的小伙伴可以了解一下

背景

一個(gè)支持拖拽操作的 CSV 文件批量編碼轉(zhuǎn)換工具,可以將各種編碼的 CSV 文件統(tǒng)一轉(zhuǎn)換為 UTF-8 編碼,解決中文亂碼問(wèn)題。

功能特點(diǎn)

多種文件添加方式

  • 拖拽支持:直接將 CSV 文件或包含 CSV 的文件夾拖拽到程序窗口
  • 單文件選擇:支持選擇單個(gè)或多個(gè) CSV 文件
  • 文件夾批量:選擇文件夾,自動(dòng)收集其中的所有 CSV 文件

智能文件管理

  • 自動(dòng)去重:重復(fù)添加的文件會(huì)被自動(dòng)過(guò)濾
  • 列表管理:支持移除選中文件、清空列表等操作
  • 實(shí)時(shí)反饋:狀態(tài)欄顯示當(dāng)前文件數(shù)量和操作結(jié)果

強(qiáng)大的編碼兼容性

  • 多編碼支持:自動(dòng)嘗試 MBCS、ANSI、UTF-8、UTF-8-SIG 等編碼
  • 智能識(shí)別:按優(yōu)先級(jí)依次嘗試,最大程度避免亂碼
  • 統(tǒng)一輸出:所有文件統(tǒng)一轉(zhuǎn)換為 UTF-8 編碼

現(xiàn)代化界面

  • 美觀布局:使用 ttk 控件,界面清晰美觀
  • 進(jìn)度可視化:實(shí)時(shí)進(jìn)度條顯示轉(zhuǎn)換進(jìn)度
  • 狀態(tài)提示:底部狀態(tài)欄顯示當(dāng)前操作狀態(tài)

系統(tǒng)要求

Python 版本:3.7 或更高版本

操作系統(tǒng):Windows、macOS、Linux(推薦 Windows)

可選依賴:tkinterdnd2(用于拖拽功能)

安裝與運(yùn)行

基礎(chǔ)運(yùn)行

python main.py

啟用拖拽功能(推薦)

pip install tkinterdnd2
python main.py

提示:如果未安裝 tkinterdnd2,程序會(huì)自動(dòng)降級(jí)運(yùn)行,并在界面提示安裝方法。

使用指南

步驟 1:添加文件

有三種方式添加需要轉(zhuǎn)換的 CSV 文件:

1.拖拽方式(推薦)

  • 直接將 CSV 文件拖拽到文件列表區(qū)域
  • 也可以拖拽包含 CSV 文件的文件夾

2.按鈕選擇

  • 點(diǎn)擊「添加文件…」選擇單個(gè)或多個(gè) CSV 文件
  • 點(diǎn)擊「添加文件夾…」選擇包含 CSV 的文件夾

3.列表管理

  • 選中文件后點(diǎn)擊「移除選中」刪除不需要的文件
  • 點(diǎn)擊「清空列表」清除所有文件

步驟 2:設(shè)置輸出目錄

  • 在「輸出設(shè)置」區(qū)域點(diǎn)擊「瀏覽…」按鈕
  • 選擇一個(gè)用于保存轉(zhuǎn)換后文件的目錄
  • 建議選擇空目錄,避免同名文件被覆蓋

步驟 3:開始轉(zhuǎn)換

  • 點(diǎn)擊「開始轉(zhuǎn)換」按鈕
  • 觀察進(jìn)度條和狀態(tài)欄的實(shí)時(shí)反饋
  • 轉(zhuǎn)換完成后會(huì)彈出結(jié)果提示框

技術(shù)實(shí)現(xiàn)

編碼檢測(cè)策略

程序采用多重編碼嘗試機(jī)制:

encodings = ['mbcs', 'ansi', 'utf-8', 'utf-8-sig']

按優(yōu)先級(jí)依次嘗試讀取,一旦成功即停止嘗試,確保最大兼容性。

文件處理流程

  • 文件收集:掃描指定路徑,過(guò)濾 .csv 文件
  • 編碼檢測(cè):按策略嘗試不同編碼讀取
  • 內(nèi)容轉(zhuǎn)換:逐行讀取并寫入 UTF-8 文件
  • 進(jìn)度反饋:實(shí)時(shí)更新界面狀態(tài)

拖拽功能實(shí)現(xiàn)

使用 tkinterdnd2 庫(kù)實(shí)現(xiàn)跨平臺(tái)拖拽支持:

self.listbox.drop_target_register(DND_FILES)
self.listbox.dnd_bind('<<Drop>>', self._on_drop)

完整代碼

import csv
import os
import sys
import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

# 嘗試啟用拖拽支持(需要安裝: pip install tkinterdnd2)
try:
    from tkinterdnd2 import DND_FILES, TkinterDnD  # type: ignore
    DND_AVAILABLE = True
except Exception:
    DND_AVAILABLE = False
    TkinterDnD = None  # 占位,未啟用時(shí)不使用


def is_csv_file(path: str) -> bool:
    return os.path.isfile(path) and path.lower().endswith('.csv')


def collect_csv_from_dir(folder: str):
    files = []
    if os.path.isdir(folder):
        for f in os.listdir(folder):
            full = os.path.join(folder, f)
            if is_csv_file(full):
                files.append(full)
    return files


def parse_dnd_event_data(root: tk.Tk, data: str):
    # 解析拖拽數(shù)據(jù),兼容包含空格的路徑
    try:
        parts = root.tk.splitlist(data)
    except Exception:
        parts = data.split()
    return [p.strip('{').strip('}') for p in parts]


class App:
    def __init__(self, root: tk.Tk):
        self.root = root
        self.root.title("CSV 文件轉(zhuǎn)換UTF-8格式 工具(支持拖拽/選擇文件/選擇文件夾)")
        self.root.geometry('760x560')
        self.root.minsize(680, 480)

        self.files = []  # 去重使用
        self.files_set = set()

        self.output_folder_var = tk.StringVar()

        self._build_ui()

    def _build_ui(self):
        # ========== 輸入?yún)^(qū)域(列表 + 拖拽) ==========
        input_frame = ttk.LabelFrame(self.root, text="待轉(zhuǎn)換文件(將 CSV 文件或文件夾拖拽到此區(qū)域)")
        input_frame.pack(fill=tk.BOTH, expand=True, padx=12, pady=(12, 6))

        list_frame = ttk.Frame(input_frame)
        list_frame.pack(fill=tk.BOTH, expand=True, padx=8, pady=8)

        self.listbox = tk.Listbox(list_frame, selectmode=tk.EXTENDED)
        self.listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.listbox.config(yscrollcommand=scrollbar.set)

        hint_text = "提示:可點(diǎn)擊下方按鈕添加文件/文件夾,也可直接拖拽 CSV 文件或文件夾到列表中。"
        self.hint_label = ttk.Label(input_frame, text=hint_text, foreground="#666")
        self.hint_label.pack(anchor='w', padx=10, pady=(0, 8))

        # 拖拽支持
        if DND_AVAILABLE and isinstance(self.root, TkinterDnD.Tk):
            try:
                self.listbox.drop_target_register(DND_FILES)
                self.listbox.dnd_bind('<<Drop>>', self._on_drop)
            except Exception:
                pass
        else:
            if not DND_AVAILABLE:
                warn = "(未安裝 tkinterdnd2,拖拽功能不可用??蓤?zhí)行: pip install tkinterdnd2)"
                self.hint_label.configure(text=f"{hint_text}\n{warn}")

        # ========== 操作按鈕 ==========
        btns = ttk.Frame(self.root)
        btns.pack(fill=tk.X, padx=12, pady=(0, 6))

        ttk.Button(btns, text="添加文件…", command=self.add_files_dialog).pack(side=tk.LEFT, padx=(0, 6))
        ttk.Button(btns, text="添加文件夾…", command=self.add_folder_dialog).pack(side=tk.LEFT, padx=(0, 6))
        ttk.Button(btns, text="移除選中", command=self.remove_selected).pack(side=tk.LEFT, padx=(0, 6))
        ttk.Button(btns, text="清空列表", command=self.clear_list).pack(side=tk.LEFT)

        # ========== 輸出設(shè)置 ==========
        out_frame = ttk.LabelFrame(self.root, text="輸出設(shè)置")
        out_frame.pack(fill=tk.X, padx=12, pady=6)

        row = ttk.Frame(out_frame)
        row.pack(fill=tk.X, padx=10, pady=8)

        ttk.Label(row, text="輸出文件夾:").pack(side=tk.LEFT)
        self.out_entry = ttk.Entry(row, textvariable=self.output_folder_var)
        self.out_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=6)
        ttk.Button(row, text="瀏覽…", command=self.select_output_folder).pack(side=tk.LEFT)

        # ========== 轉(zhuǎn)換 & 進(jìn)度 ==========
        bottom = ttk.Frame(self.root)
        bottom.pack(fill=tk.X, padx=12, pady=10)

        self.progress = ttk.Progressbar(bottom, mode='determinate')
        self.progress.pack(fill=tk.X, expand=True, side=tk.LEFT, padx=(0, 10))

        ttk.Button(bottom, text="開始轉(zhuǎn)換", command=self.convert_files).pack(side=tk.RIGHT)

        # 狀態(tài)欄
        self.status_var = tk.StringVar(value="準(zhǔn)備就緒")
        status = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor='w')
        status.pack(fill=tk.X, side=tk.BOTTOM)

    # ---------- 文件源管理 ----------
    def _add_paths(self, paths):
        added = 0
        for p in paths:
            if os.path.isdir(p):
                for f in collect_csv_from_dir(p):
                    if f not in self.files_set:
                        self.files.append(f)
                        self.files_set.add(f)
                        self.listbox.insert(tk.END, f)
                        added += 1
            else:
                if is_csv_file(p) and p not in self.files_set:
                    self.files.append(p)
                    self.files_set.add(p)
                    self.listbox.insert(tk.END, p)
                    added += 1
        self.status_var.set(f"已添加 {added} 個(gè)文件,當(dāng)前總數(shù):{len(self.files)}")

    def _on_drop(self, event):
        paths = parse_dnd_event_data(self.root, event.data)
        self._add_paths(paths)

    def add_files_dialog(self):
        paths = filedialog.askopenfilenames(title="選擇 CSV 文件", filetypes=[("CSV 文件", "*.csv"), ("所有文件", "*.*")])
        if paths:
            self._add_paths(paths)

    def add_folder_dialog(self):
        folder = filedialog.askdirectory(title="選擇包含 CSV 的文件夾")
        if folder:
            self._add_paths([folder])

    def remove_selected(self):
        indices = list(self.listbox.curselection())
        if not indices:
            return
        # 從后向前刪除,避免索引錯(cuò)亂
        for idx in reversed(indices):
            path = self.listbox.get(idx)
            self.listbox.delete(idx)
            if path in self.files_set:
                self.files_set.remove(path)
            if path in self.files:
                self.files.remove(path)
        self.status_var.set(f"已移除,當(dāng)前總數(shù):{len(self.files)}")

    def clear_list(self):
        self.listbox.delete(0, tk.END)
        self.files.clear()
        self.files_set.clear()
        self.status_var.set("列表已清空")

    def select_output_folder(self):
        folder = filedialog.askdirectory(title="請(qǐng)選擇保存轉(zhuǎn)換后的文件夾")
        if folder:
            self.output_folder_var.set(folder)

    # ---------- 轉(zhuǎn)換邏輯 ----------
    def _read_rows_with_encodings(self, file_path):
        # 按順序嘗試不同編碼讀取
        encodings = ['mbcs', 'ansi', 'utf-8', 'utf-8-sig']
        last_err = None
        for enc in encodings:
            try:
                with open(file_path, newline='', encoding=enc) as csvfile:
                    reader = csv.reader(csvfile, delimiter=',', quotechar='"')
                    for row in reader:
                        yield row
                return
            except Exception as e:
                last_err = e
                continue
        # 如果都失敗,再拋出最后的異常
        raise last_err if last_err else UnicodeDecodeError("codec", b"", 0, 1, "無(wú)法解碼")

    def convert_files(self):
        if not self.files:
            messagebox.showwarning("提示", "請(qǐng)先添加需要轉(zhuǎn)換的 CSV 文件或文件夾!")
            return

        output_folder = self.output_folder_var.get().strip()
        if not output_folder:
            messagebox.showerror("錯(cuò)誤", "請(qǐng)選擇保存轉(zhuǎn)換后的文件夾!")
            return
        if not os.path.exists(output_folder):
            try:
                os.makedirs(output_folder, exist_ok=True)
            except Exception as e:
                messagebox.showerror("錯(cuò)誤", f"無(wú)法創(chuàng)建輸出文件夾:{e}")
                return

        total = len(self.files)
        self.progress.config(maximum=total, value=0)
        success, failed = 0, 0

        for i, src in enumerate(self.files, start=1):
            dst = os.path.join(output_folder, os.path.basename(src))
            try:
                with open(dst, 'w', newline='', encoding='utf-8') as f_w:
                    writer = csv.writer(f_w)
                    for row in self._read_rows_with_encodings(src):
                        writer.writerow(row)
                success += 1
                self.status_var.set(f"轉(zhuǎn)換成功:{os.path.basename(src)}")
            except Exception as e:
                failed += 1
                self.status_var.set(f"轉(zhuǎn)換失敗:{os.path.basename(src)} -> {e}")
            finally:
                self.progress['value'] = i
                self.root.update_idletasks()

        msg = f"轉(zhuǎn)換完成!成功:{success},失敗:{failed}。輸出目錄:{output_folder}"
        if failed:
            messagebox.showwarning("完成(部分失?。?, msg)
        else:
            messagebox.showinfo("完成", msg)


def main():
    # 優(yōu)先使用帶 DnD 的 Tk
    if DND_AVAILABLE:
        root = TkinterDnD.Tk()
    else:
        root = tk.Tk()
    # Windows 上 ttk 默認(rèn)樣式更美觀
    try:
        ttk.Style().theme_use('clam')
    except Exception:
        pass

    app = App(root)
    root.mainloop()


if __name__ == '__main__':
    main()


效果圖

常見問(wèn)題

Q: 為什么拖拽功能不可用

A: 需要安裝 tkinterdnd2 庫(kù)。運(yùn)行 pip install tkinterdnd2 后重啟程序即可。

Q: 轉(zhuǎn)換后 Excel 打開仍有亂碼

A: 本工具輸出標(biāo)準(zhǔn) UTF-8 格式。部分舊版 Excel 可能需要 UTF-8-BOM 格式,可以考慮修改輸出編碼為 utf-8-sig。

Q: 輸出文件會(huì)覆蓋原文件嗎

A: 不會(huì)。程序會(huì)在指定的輸出目錄創(chuàng)建新文件,不會(huì)修改原始文件。但如果輸出目錄中存在同名文件,會(huì)被覆蓋。

Q: 支持哪些分隔符

A: 目前默認(rèn)支持逗號(hào)分隔符。如需支持其他分隔符(如分號(hào)、制表符),可以擴(kuò)展使用 csv.Sniffer 進(jìn)行自動(dòng)檢測(cè)。

使用建議

最佳實(shí)踐

  • 批量處理:將同類型的 CSV 文件放在同一文件夾,整體拖拽添加
  • 輸出管理:始終選擇空的輸出目錄,避免文件覆蓋
  • 編碼兼容:如需與特定軟件兼容,可調(diào)整輸出編碼格式

性能優(yōu)化

  • 大文件處理時(shí),程序會(huì)顯示實(shí)時(shí)進(jìn)度
  • 支持中斷操作(關(guān)閉程序窗口)
  • 內(nèi)存占用優(yōu)化,逐行處理避免大文件內(nèi)存溢出

擴(kuò)展功能規(guī)劃

  • 輸出文件名自動(dòng)添加后綴,避免覆蓋
  • 自動(dòng)分隔符檢測(cè)與配置
  • 轉(zhuǎn)換報(bào)告導(dǎo)出(成功/失敗統(tǒng)計(jì))
  • 遞歸掃描子目錄選項(xiàng)
  • 編碼檢測(cè)結(jié)果預(yù)覽
  • 批量重命名功能

開發(fā)者: 專注于提供簡(jiǎn)單可靠的數(shù)據(jù)處理工具

到此這篇關(guān)于Python實(shí)現(xiàn)CSV文件編碼轉(zhuǎn)換工具(轉(zhuǎn)成UTF-8格式)的文章就介紹到這了,更多相關(guān)Python轉(zhuǎn)換csv文件編碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • pip命令突然無(wú)法使用問(wèn)題以及解決

    pip命令突然無(wú)法使用問(wèn)題以及解決

    當(dāng)你在使用pip安裝Python庫(kù)時(shí)遇到問(wèn)題,可以嘗試以下兩種解決方案,第一種是直接在Scripts文件夾內(nèi)使用CMD命令進(jìn)行安裝,第二種是將Scripts的路徑設(shè)置為系統(tǒng)環(huán)境變量,這樣就可以直接在dos中使用pip install進(jìn)行安裝了,以上解決方案僅供參考,如有更好的方法歡迎交流分享
    2024-10-10
  • 探究Python中isalnum()方法的使用

    探究Python中isalnum()方法的使用

    這篇文章主要介紹了探究Python中isalnum()方法的使用,是Python入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-05-05
  • python 如何在 Matplotlib 中繪制垂直線

    python 如何在 Matplotlib 中繪制垂直線

    這篇文章主要介紹了python 如何在 Matplotlib 中繪制垂直線,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-04-04
  • Python?selenium?八種定位元素的方式

    Python?selenium?八種定位元素的方式

    這篇文章主要介紹了Python?selenium八種定位元素的方式,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • 使用PyInstaller將Python程序文件轉(zhuǎn)換為可執(zhí)行程序文件

    使用PyInstaller將Python程序文件轉(zhuǎn)換為可執(zhí)行程序文件

    與py2exe一樣,PyInstaller程序也可以將Python的.py程序文件轉(zhuǎn)換為.exe,并且還有Linux的版本,下面我們就來(lái)詳細(xì)看一下如何使用PyInstaller將Python程序文件轉(zhuǎn)換為可執(zhí)行程序文件
    2016-07-07
  • python爬取晉江文學(xué)城小說(shuō)評(píng)論(情緒分析)

    python爬取晉江文學(xué)城小說(shuō)評(píng)論(情緒分析)

    這篇文章主要介紹了使用python爬取晉江文學(xué)城小說(shuō)評(píng)論(情緒分析),全文代碼詳細(xì),邏輯清晰,很適合學(xué)習(xí)爬蟲爬取的朋友,需要的朋友可以參考下
    2021-04-04
  • scrapy實(shí)踐之翻頁(yè)爬取的實(shí)現(xiàn)

    scrapy實(shí)踐之翻頁(yè)爬取的實(shí)現(xiàn)

    這篇文章主要介紹了scrapy實(shí)踐之翻頁(yè)爬取的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 把csv文件轉(zhuǎn)化為數(shù)組及數(shù)組的切片方法

    把csv文件轉(zhuǎn)化為數(shù)組及數(shù)組的切片方法

    今天小編就為大家分享一篇把csv文件轉(zhuǎn)化為數(shù)組及數(shù)組的切片方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • python基礎(chǔ)詳解之if循環(huán)語(yǔ)句

    python基礎(chǔ)詳解之if循環(huán)語(yǔ)句

    這篇文章主要介紹了python基礎(chǔ)詳解之if循環(huán)語(yǔ)句,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)python的小伙伴們有很好的幫助需要的朋友可以參考下
    2021-04-04
  • Python調(diào)用C/C++函數(shù)庫(kù)的多種方法與實(shí)踐指南

    Python調(diào)用C/C++函數(shù)庫(kù)的多種方法與實(shí)踐指南

    Python作為一門高級(jí)編程語(yǔ)言,以其簡(jiǎn)潔的語(yǔ)法和豐富的庫(kù)生態(tài)贏得了開發(fā)者的青睞,然而,在計(jì)算密集型任務(wù)中,Python的性能往往無(wú)法滿足要求,Python調(diào)用C/C++函數(shù)庫(kù)成為提升應(yīng)用性能的關(guān)鍵技術(shù)路徑,本文將深入探討Python調(diào)用C/C++函數(shù)庫(kù)的多種方法,需要的朋友可以參考下
    2025-08-08

最新評(píng)論