ZhangZhihui's Blog  

 

dir_path = 'D:/VSCodeWorkspace/ZZH/'
filename = 'a.csv'

with codecs.open(dir_path+filename, 'r',encoding='utf-8') as srcFile, codecs.open(dir_path+filename+ '.tmp', 'w',encoding='utf-8') as dstFile:
        fileReader = csv.reader(srcFile, delimiter=',')
        fileWriter = csv.writer(dstFile,quoting=csv.QUOTE_ALL,delimiter='\t')
        for d in list(fileReader):
            for ii,dd in enumerate(d):
                dd = dd.replace('\r\n',',')
                dd = dd.replace('\n\r',',')
                dd = dd.replace('\n',',')
                dd = dd.replace('\r',',')
                dd=dd.replace('\t',' ')
                d[ii] = dd
            fileWriter.writerow(d)
        dstFile.close()
        srcFile.close()

 

上面代码中的dd.replace不会起什么作用,对吗?

 

你的感觉是对的 👍

在你贴的代码里,这几行:

dd = dd.replace('\r\n', ',')
dd = dd.replace('\n\r', ',')
dd = dd.replace('\n', ',')
dd = dd.replace('\r', ',')
dd = dd.replace('\t', ' ')
d[ii] = dd

 

确实 不会起什么作用,原因有两个:


1. csv.reader 已经帮你处理掉了行结束符

  • csv.reader(srcFile, delimiter=',') 读取时会自动去掉 \r\n 等换行符,它们不会作为字段内容传递进来。

  • 所以正常情况下,dd 里已经不会有换行符 \r\n

  • 你对 dd.replace('\n', ','),基本不会替换到任何东西。


2. \t 也不会出现(除非字段里本来就有制表符)

  • 因为原始 CSV 的分隔符是 ,,所以除非某个字段文本里真的有 \t 字符,否则 dd.replace('\t',' ') 也不会生效。


✅ 总结:

  • \r\n\n\rreplace 几乎没有效果,因为 csv.reader 已经处理掉了行结束符。

  • \treplace 可能有效,但前提是 CSV 里的某个字段真的包含制表符。


👉 建议:如果你真正的目标是“清理掉字段里的换行符和制表符”,可以改成:

for d in fileReader:
    d = [field.replace('\r', ',')
              .replace('\n', ',')
              .replace('\t', ' ')
         for field in d]
    fileWriter.writerow(d)

 

更简洁,不用 enumerate


要不要我帮你写一个更“正统”的 CSV 清洗脚本,能同时解决编码、换行、分隔符等问题?

 
You said:
要,谢谢。
 
ChatGPT said:

好的 👍 我给你写一个更“正统”的 CSV 清洗脚本,目标是:

  • 自动处理文件编码(支持 UTF-8 / GBK 等);

  • 保证不会因为换行符或制表符而破坏 CSV 格式;

  • 输入是 逗号分隔的 CSV,输出是 制表符分隔并且所有字段带引号的 CSV


📝 示例代码(推荐用 pathlib 来管理路径)

import csv
from pathlib import Path

# 输入输出文件
dir_path = Path("D:/VSCodeWorkspace/ZZH")
src_file = dir_path / "a.csv"
dst_file = dir_path / "a.csv.tmp"

# 打开文件,推荐用内置 open 而不是 codecs.open
# newline='' 非常重要,避免 csv.writer 重复写入换行
with open(src_file, 'r', encoding='utf-8', newline='') as f_in, \
     open(dst_file, 'w', encoding='utf-8', newline='') as f_out:

    reader = csv.reader(f_in, delimiter=',')
    writer = csv.writer(f_out, delimiter='\t', quoting=csv.QUOTE_ALL)

    for row in reader:
        # 清洗字段:去掉内部换行符、替换制表符
        cleaned = [
            field.replace('\r', ',')
                 .replace('\n', ',')
                 .replace('\t', ' ')
            for field in row
        ]
        writer.writerow(cleaned)

 


🚩 注意点

  1. newline=''

    • 必须加在 open() 里,否则 csv.writer 在 Windows 上会写出多余的空行。

  2. 编码

    • 如果源文件不是 UTF-8(比如 GBK),可以改成:

      with open(src_file, 'r', encoding='gbk', newline='') as f_in:

       

  3. 字段清洗

    • 上面的代码确保任何字段里出现的 \r\n 都会被替换成逗号 ,
      制表符 \t 会被替换为空格


👉 这样处理之后,你得到的 a.csv.tmp 文件就是 制表符分隔,字段全加引号,干净整齐

要不要我帮你扩展一下,加上 自动检测文件编码 的功能(用 chardet),这样就不用自己猜是 UTF-8 还是 GBK?

 
You said:
好的,谢谢。
 
ChatGPT said:

不客气 😄 下面我帮你把 自动检测编码 的功能也加上,这样你就不用手动去猜文件到底是 UTF-8、GBK 还是别的编码了。


📝 最终清洗脚本(带编码检测)

import csv
from pathlib import Path
import chardet

# 输入输出文件路径
dir_path = Path("D:/VSCodeWorkspace/ZZH")
src_file = dir_path / "a.csv"
dst_file = dir_path / "a.csv.tmp"

# 1. 先用二进制方式读取一部分文件,检测编码
with open(src_file, 'rb') as f:
    raw_data = f.read(50000)  # 取前 50KB 足够判断
    result = chardet.detect(raw_data)
    encoding = result["encoding"] or "utf-8"
    confidence = result["confidence"]
    print(f"[*] Detected encoding: {encoding} (confidence={confidence:.2f})")

# 2. 用检测到的编码打开源文件,写入新文件
with open(src_file, 'r', encoding=encoding, newline='') as f_in, \
     open(dst_file, 'w', encoding='utf-8', newline='') as f_out:

    reader = csv.reader(f_in, delimiter=',')
    writer = csv.writer(f_out, delimiter='\t', quoting=csv.QUOTE_ALL)

    for row in reader:
        # 清洗字段:换行符替换成逗号,制表符替换成空格
        cleaned = [
            field.replace('\r', ',')
                 .replace('\n', ',')
                 .replace('\t', ' ')
            for field in row
        ]
        writer.writerow(cleaned)

print(f"[*] Cleaned file written to: {dst_file}")

 


🚀 特点

  1. 自动检测文件编码

    • chardet 检测,常见的 UTF-8、GBK、GB2312、ISO-8859-1 等都能识别。

    • 如果检测失败,就默认用 UTF-8。

  2. 统一输出 UTF-8 文件

    • 即使源文件是 GBK 编码,最后得到的 .tmp 文件也是 UTF-8 编码,更通用。

  3. 字段清洗规则

    • 把字段里的 \r\n → 逗号 ,

    • \t → 空格 ' '

    • 防止字段里的换行符破坏 CSV 格式。


👉 建议你第一次运行时,观察 print 出来的 Detected encoding: ... 是否符合预期。

要不要我再帮你写一个小函数,把这个逻辑封装成 clean_csv(src, dst),以后可以直接复用?

 
You said:
好的。
 
ChatGPT said:

太好了 👍 我帮你把逻辑封装成一个可复用的函数 clean_csv(src, dst),这样以后清理任何 CSV 文件都能直接调用。


📝 封装好的函数

import csv
from pathlib import Path
import chardet

def clean_csv(src, dst, src_delimiter=',', dst_delimiter='\t'):
    """
    清理 CSV 文件:
    - 自动检测输入文件编码
    - 替换字段内的换行符(\r,\n)为逗号
    - 替换字段内的制表符(\t)为空格
    - 输出为 UTF-8 编码,字段全部带引号
    
    参数:
        src (str|Path): 输入文件路径
        dst (str|Path): 输出文件路径
        src_delimiter (str): 输入文件的分隔符,默认逗号
        dst_delimiter (str): 输出文件的分隔符,默认制表符
    """
    src = Path(src)
    dst = Path(dst)

    # 1. 自动检测编码
    with open(src, 'rb') as f:
        raw_data = f.read(50000)  # 取前 50KB 足够判断
        result = chardet.detect(raw_data)
        encoding = result["encoding"] or "utf-8"
        confidence = result["confidence"]
        print(f"[*] Detected encoding for {src.name}: {encoding} (confidence={confidence:.2f})")

    # 2. 按检测到的编码读取,统一输出 UTF-8
    with open(src, 'r', encoding=encoding, newline='') as f_in, \
         open(dst, 'w', encoding='utf-8', newline='') as f_out:

        reader = csv.reader(f_in, delimiter=src_delimiter)
        writer = csv.writer(f_out, delimiter=dst_delimiter, quoting=csv.QUOTE_ALL)

        for row in reader:
            cleaned = [
                field.replace('\r', ',')
                     .replace('\n', ',')
                     .replace('\t', ' ')
                for field in row
            ]
            writer.writerow(cleaned)

    print(f"[*] Cleaned file written to: {dst}")

 


🚀 使用示例

# 假设你的文件路径
src_file = "D:/VSCodeWorkspace/ZZH/a.csv"
dst_file = "D:/VSCodeWorkspace/ZZH/a.csv.tmp"

# 调用函数
clean_csv(src_file, dst_file)

 

这样就能得到一个 干净的、UTF-8 编码的、制表符分隔并且带引号 的 CSV 文件。

 

posted on 2025-09-16 08:54  ZhangZhihuiAAA  阅读(12)  评论(0)    收藏  举报