将 CSV 文件内容与 filecmp 进行比较并忽略元数据

2024-01-04

import filecmp

comparison = filecmp.dircmp(dir_local, dir_server)
comparison.report_full_closure()

我想将本地计算机上保存的所有 CSV 文件与服务器上保存的文件进行比较。它们的文件夹结构是相同的。我只想做一个数据对比 and 不是元数据(如创建时间等)。我在用filecmp但它似乎执行元数据比较。有办法做我想做的事吗?


有多种方法可以比较 2 个存储库(服务器文件系统和本地文件系统)之间的 .csv 文件。


方法一:使用hashlib

该方法使用Python模块hashlib.我使用哈希算法 sha256 来计算文件的哈希摘要。我将文件的哈希值与确切的文件名进行比较。此方法效果很好,但它会忽略两个目录中不存在的任何文件。

import hashlib

def compare_common_files_by_hash(directory_one, directory_two):
   d1_files = set(os.listdir(directory_one))
   d2_files = set(os.listdir(directory_two))
   common_files = list(d1_files &  d2_files)
   if common_files:
     for filename in common_files:
        hash_01 = hashlib.sha256(open(f'{directory_one}/{filename}', 'rb').read()).hexdigest()
        hash_02 = hashlib.sha256(open(f'{directory_two}/{filename}', 'rb').read()).hexdigest()
        if hash_01 == hash_02:
            print(f'The file - {filename} is identical in the directories {directory_one} and {directory_two}')
        elif hash_01 != hash_02:
            print(f'The file - {filename} is different in the directories {directory_one} and {directory_two}')

方法2:使用os st_size

该方法使用Python模块os.在此示例中,我比较了文件的大小。此方法工作正常,但它会对任何具有任何数据更改且不会更改文件大小的文件进行错误分类。

import os 

def compare_common_files_by_size(directory_one, directory_two):
  d1_files = set(os.listdir(directory_one))
  d2_files = set(os.listdir(directory_two))
  common_files = list(d1_files &  d2_files)
  if common_files:
    for filename in common_files:
       file_01 = os.stat(f'{directory_one}/{filename}')
       file_02 = os.stat(f'{directory_two}/{filename}')
       if file_01.st_size == file_02.st_size:
            print(f'The file - {filename} is identical in the directories {directory_one} and {directory_two}')
       elif file_01.st_size != file_02.st_size:
            print(f'The file - {filename} is different in the directories {directory_one} and'
                  f' {directory_two}')

方法3:使用os st_size和st_mtime

该方法也使用Python模块os.在这个例子中,我不仅比较了文件的大小,还比较了最后的修改时间。此方法效果很好,但会将文件错误地分类为相同。在测试中,我保存了一个没有数据修改的文件,操作系统时间将文件标记为不同,但实际上并没有真正不同。

import os

 def compare_common_files_by_metadata(directory_one, directory_two):
   d1_files = set(os.listdir(directory_one))
   d2_files = set(os.listdir(directory_two))
   common_files = list(d1_files & d2_files)
   if common_files:
     for filename in common_files:
        file_01 = os.stat(f'{directory_one}/{filename}')
        file_02 = os.stat(f'{directory_two}/{filename}')
        if file_01.st_size == file_02.st_size and file_01.st_mtime == file_02.st_mtime:
            print(f'The file - {filename} is identical in the directories {directory_one} and {directory_two}')
        elif file_01.st_size != file_02.st_size or file_01.st_mtime != file_02.st_mtime:
            print(f'The file - {filename} is different in the directories {directory_one} and'
                  f' {directory_two}')

方法4:使用set()

本示例使用Pythonset()确定两个同名 csv 文件之间的行与行之间的差异。此方法将输出 2 个 csv 文件之间的精确变化。

import os

def compare_common_files_by_lines(directory_one, directory_two):
   d1_files = set(os.listdir(directory_one))
   d2_files = set(os.listdir(directory_two))
   common_files = list(d1_files & d2_files)
   if common_files:
     for filename in common_files:
        if fileName.endswith('.csv'):
          file_01 = open(f'{directory_one}/{filename}', 'r', encoding='ISO-8859-1')
          file_02 = open(f'{directory_two}/{filename}', 'r', encoding='ISO-8859-1')
          csv_file_01 = set(map(tuple, csv.reader(file_01)))
          csv_file_02 = set(map(tuple, csv.reader(file_02)))
          different = csv_file_01 ^ csv_file_02
            for row in sorted(different, key=lambda x: x, reverse=True):
               if row:
                  print(f'This row: \n {row} \n was different between the file {fileName} in the directories'
                          f' {directory_one} and {directory_two}')

方法5:使用文件cmp.cmp

该方法使用Python模块filecmp.在这个例子中我使用了文件cmp.cmp with shallow set to False。将此参数设置为False指示filecmp查看文件的内容而不是元数据,例如文件大小,这是默认的文件cmp.cmp。此方法与使用的方法 1 一样有效hashlib.

import filecmp

def compare_common_files(directory_one, directory_two):
  d1_files = set(os.listdir(directory_one))
  d2_files = set(os.listdir(directory_two))
  common_files = list(d1_files & d2_files)
  if common_files:
    for filename in common_files:
        file_01 = f'{directory_one}/{filename}'
        file_02 = f'{directory_two}/{filename}'
        comparison = filecmp.cmp(file_01, file_02, shallow=False)
        if comparison:
            print(f'The file - {filename} is identical in the directories - {directory_one} and {directory_two}')
        elif not comparison:
            print(f'The file - {filename} is different in the directories - {directory_one} and {directory_two}')

方法6:使用filecmp.dircmp

该方法也使用Python模块filecmp.在这个例子中我使用了文件cmp.dircmp,这使我不仅可以识别两个目录之间不常见的文件,还可以找到那些名称相似但内容不同的文件。

import filecmp

def directory_recursive(directory_one, directory_two):
   files = filecmp.dircmp(directory_one, directory_two)
   for filename in files.diff_files:
      print(f'The file - {filename} is different in the directories - {files.left} and {files.right}')
   for filename in files.left_only:
      print(f'The file - {filename} - was only found in the directory {files.left}')
   for filename in files.right_only:
      print(f'The file - {filename} - was only found in the directory {files.right}')

方法七:逐行比较

此示例对 2 个 csv 文件进行逐行比较,并输出不同的行。输出可以添加到 Python 字典或 JSON 文件中以供辅助。

import csv

def get_csv_file_lines(file):
   with open(file, 'r', encoding='utf-8') as csv_file:
      rows = csv.reader(csv_file)
      for row in rows:
         yield row

def compare_csv_files_line_by_line(csv_file_one, csv_file_two):
   csvfile_02 = get_csv_file_lines(csv_file_two)
   for line_one in get_csv_file_lines(csv_file_one):
      line_two = csvfile_02.__next__()
      if line_two != line_one:
        print('File names being compared:')
        print(f'csv_file_one: {csv_file_one}')
        print(f'csv_file_two: {csv_file_two}')
        print(f'The following rows have difference in the files being compared.')
        print('csv_file_one:', line_one)
        print('csv_file_two:', line_two)
        print('\n')

使用 hashlib 将本地文件系统存储到 S3 存储桶

下面的示例是用于比较本地文件系统和远程 S3 存储桶之间的文件的真实用例。我原本打算使用对象.e_tagAWS S3 创建的标签,但该标签可能存在问题,不应在哈希比较操作中使用。我决定查询 S3 并将单个文件加载到内存文件系统中,该文件系统可以在每次比较操作期间查询和清空。这个方法效果很好,对我的系统性能没有产生不利影响。

import fs
import os
import boto3
import hashlib

def create_temp_memory_filesystem():
   mem_fs = fs.open_fs('mem://')
   virtual_disk = mem_fs.makedir('hidden_dir')
   return mem_fs, virtual_disk

def query_s3_file_by_name(filename, memory_filesystem, temp_directory):
   s3 = boto3.resource('s3', aws_access_key_id='your_access_key_id',
                    aws_secret_access_key='your_secret_access_key')
   bucket = s3.Bucket('your_bucket_name')
   for obj in bucket.objects.all():
      if obj.key == filename:
        body = obj.get()['Body'].read()
        with memory_filesystem.open(f'{temp_directory}/s3_{filename}', 'w') as f:
            f.write(str(body))
            f.close()

 def compare_local_files_to_s3_files(local_csv_files):
    virtual_disk = create_temp_memory_filesystem()
    directory_name = str(virtual_disk[1]).split('/')[1]
    files = set(os.listdir(local_csv_files))
    for filename in files:
       if filename.endswith('.csv'):
         local_file_hash = hashlib.sha256(open(f'{local_csv_files}/{filename}', 'rb').read()).hexdigest()
         query_s3_file_by_name(filename, virtual_disk[0], directory_name)
         virtual_files = virtual_disk[0].opendir(directory_name)
         for file_name in virtual_files.listdir('/'):
            s3_file_hash = hashlib.sha256(open(file_name, 'rb').read()).hexdigest()
            if local_file_hash == s3_file_hash:
                print(f'The file - {filename} is identical in both the local file system and the S3 bucket.')
            elif local_file_hash != s3_file_hash:
                print(f'The file - {filename} is different between the local file system and the S3 bucket.')
            virtual_files.remove(file_name)
    virtual_disk[0].close()

使用 filecmp 将本地文件系统存储到 S3 存储桶

这个例子与上面的例子相同,除了我使用文件cmp.cmp代替hashlib用于比较操作。

import fs
import os
import boto3
import filecmp

def create_temp_memory_filesystem():
   mem_fs = fs.open_fs('mem://')
   virtual_disk = mem_fs.makedir('hidden_dir')
   return mem_fs, virtual_disk

def query_s3_file_by_name(filename, memory_filesystem, temp_directory):
   s3 = boto3.resource('s3', aws_access_key_id='your_access_key_id',
                    aws_secret_access_key='your_secret_access_key')
   bucket = s3.Bucket('your_bucket_name')
   for obj in bucket.objects.all():
      if obj.key == filename:
        body = obj.get()['Body'].read()
        with memory_filesystem.open(f'{temp_directory}/s3_{filename}', 'w') as f:
            f.write(str(body))
            f.close()

def compare_local_files_to_s3_files(local_csv_files):
   virtual_disk = create_temp_memory_filesystem()
   directory_name = str(virtual_disk[1]).split('/')[1]
   files = set(os.listdir(local_csv_files))
   for filename in files:
      if filename.endswith('.csv'):
        local_file = f'{local_csv_files}/{filename}'
        query_s3_file_by_name(filename, virtual_disk[0], directory_name)
        virtual_files = virtual_disk[0].opendir(directory_name)
        for file_name in virtual_files.listdir('/'):
            comparison = filecmp.cmp(local_file, file_name, shallow=False)
            if comparison:
                print(f'The file - {filename} is identical in both the local file system and the S3 bucket.')
            elif not comparison:
                print(f'The file - {filename} is different between the local file system and the S3 bucket.')
            virtual_files.remove(file_name)
   virtual_disk[0].close()

使用 hashlib 的本地文件系统到 Google Cloud 存储桶

此示例与上面的 S3 hashlib 代码示例类似,但它使用 Google Cloud 存储桶。

import fs
import os
import hashlib
from google.cloud import storage

def create_temp_memory_filesystem():
   mem_fs = fs.open_fs('mem://')
   virtual_disk = mem_fs.makedir('hidden_dir')
   return mem_fs, virtual_disk

def query_google_cloud_storage_file_by_name(filename, memory_filesystem, temp_directory):
  client = storage.Client.from_service_account_json('path_to_your_credentials.json')
  bucket = client.get_bucket('your_bucket_name')
  blobs = bucket.list_blobs()
  for blob in blobs:
     if blob.name == filename:
       with memory_filesystem.open(f'{temp_directory}/{filename}', 'w') as f:
           f.write(str(blob.download_to_filename(blob.name)))
           f.close()

def compare_local_files_to_google_storage_files(local_csv_files):
   virtual_disk = create_temp_memory_filesystem()
   directory_name = str(virtual_disk[1]).split('/')[1]
   files = set(os.listdir(local_csv_files))
   for filename in files:
      if filename.endswith('.csv'):
        local_file_hash = hashlib.sha256(open(f'{local_csv_files}/{filename}', 'rb').read()).hexdigest()
        query_google_cloud_storage_file_by_name(filename, virtual_disk[0], directory_name)
        virtual_files = virtual_disk[0].opendir(directory_name)
        for file_name in virtual_files.listdir('/'):
            gs_file_hash = hashlib.sha256(open(file_name, 'rb').read()).hexdigest()
            if local_file_hash == gs_file_hash:
                print(f'The file - {filename} is identical in both the local file system and the Google Cloud bucket.')
            elif local_file_hash != gs_file_hash:
                print(f'The file - {filename} is different between the local file system and the Google Cloud bucket.')
            virtual_files.remove(file_name)
    virtual_disk[0].close()

使用 filecmp 将本地文件系统存储到 Google Cloud 存储桶

此示例与上面的 S3 filecmp 代码示例类似,但它使用 Google Cloud 存储桶。

 import fs
 import os
 import filecmp
 from google.cloud import storage

 def create_temp_memory_filesystem():
    mem_fs = fs.open_fs('mem://')
    virtual_disk = mem_fs.makedir('hidden_dir')
    return mem_fs, virtual_disk

 def query_google_cloud_storage_file_by_name(filename, memory_filesystem, temp_directory):
   client = storage.Client.from_service_account_json('path_to_your_credentials.json')
   bucket = client.get_bucket('your_bucket_name')
   blobs = bucket.list_blobs()
   for blob in blobs:
      if blob.name == filename:
        with memory_filesystem.open(f'{temp_directory}/{filename}', 'w') as f:
            f.write(str(blob.download_to_filename(blob.name)))
            f.close()

 def compare_local_files_to_google_storage_files(local_csv_files):
   virtual_disk = create_temp_memory_filesystem()
   directory_name = str(virtual_disk[1]).split('/')[1]
   files = set(os.listdir(local_csv_files))
   for filename in files:
      if filename.endswith('.csv'):
        local_file = f'{local_csv_files}/{filename}'
        query_google_cloud_storage_file_by_name(filename, virtual_disk[0], directory_name)
        virtual_files = virtual_disk[0].opendir(directory_name)
        for file_name in virtual_files.listdir('/'):
          comparison = filecmp.cmp(local_file, file_name, shallow=False)
          if comparison:
            print(f'The file - {filename} is identical in both the local file system and the Google Cloud bucket.')
          elif not comparison:
                print(f'The file - {filename} is different between the local file system and the Google Cloud bucket.')
           virtual_files.remove(file_name)
   virtual_disk[0].close()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 CSV 文件内容与 filecmp 进行比较并忽略元数据 的相关文章

随机推荐

  • 在 C 中将动态分配的数组作为参数传递

    所以 我的主网上有一个动态分配的数组 int main int array int len array int malloc len sizeof int return EXIT SUCCESS 我还想构建一个函数来对这个动态分配的数组执行
  • jasonp跨域请求“将json包装成回调方法”

    我添加了 回调 使用匿名函数获取请求中的 url 我必须在服务器端代码中添加什么才能使其跨域工作 这里使用getJSON是否正确 这是没有 JSONP 的播放器的示例http www freeenergymedia com shared P
  • 将变量从 Scala 中的存在类型 TypeCast 转换为运行时类型

    这个线程 https stackoverflow com questions 29380839 trait runtime type of type parameter through typetag when used with exis
  • 不在网络抓取中迭代列表

    通过链接 我尝试创建两个列表 一个用于国家 地区 另一个用于货币 但是 我陷入了困境 它只给了我第一个国家 地区名称 但没有迭代到所有国家 地区的列表 任何有关如何解决此问题的帮助将不胜感激 提前致谢 这是我的尝试 from bs4 imp
  • ORDER BY 重新加载,cassandra

    我想对给定的列族进行排序 为此我尝试使用选项 CLUSTERING ORDER BY 创建一个表 我总是遇到以下错误 1 变体 A 导致错误请求 缺少列 userid 的 CLUSTERING ORDER陈述 CREATE TABLE te
  • 使用Service、TimerTask和BroadcastReceiver来检查各种更新

    我正在尝试创建一个简单的程序来执行以下操作 由我的活动 UpdateServiceActivity 启动的服务 NewsService 检查新闻 如果发现新闻 NewsService 则会向接收者 NewsReceiver 发送广播 接收到
  • Android 10秒后隐藏布局?

    我在单击按钮时显示了一个布局 我想在 10 秒后隐藏该布局 protected void onCreate Bundle savedInstanceState super onCreate savedInstanceState mVolHa
  • 在 Visual Studio 2008 中调试 Web 服务时如何避免超时错误

    我正在使用控制台应用程序调用 Web 服务方法 并使用 vs2008 中的调试器单步调试代码 有时我需要停下来思考一些事情 比较一下价值观 不是说几个小时 只是几分钟 此时web服务超时了 如何避免这种情况 让web服务根本不超时 谢谢 好
  • 如何排除和过滤pandas中的几列?

    我知道我们可以使用 pandas dataframe 过滤器仅选择几列 但是我们也可以仅排除某些列吗 这是 MWE import numpy as np import pandas as pd df pd DataFrame id 1 2
  • 如何在 MKMapView 上绘制当前位置到所需位置之间的路线?

    我想显示我当前位置和所需位置之间的路线 我能够做到这一点 但是当源点和目的地点到目前为止时 它不会显示路线并给出内存警告 您能建议任何示例代码或任何方法来做到这一点吗 以下代码用于绘制当前位置到所需位置之间的路径 void viewDidL
  • jqGrid dataUrl下拉列表不刷新

    我是 Web 开发新手 正在开发我的第一个 ASP NET MVC 3 应用程序 我正在使用 jqGrid 并注意到刷新页面不会刷新下拉列表中的值 直到我在另一个选项卡中打开同一页面 然后刷新第一个选项卡将获取更改的值 我有一个控制器操作
  • For-each 与迭代器。哪个将是更好的选择

    考虑以下场景 List
  • 将新记录添加到私人 Outlook 通讯组列表

    我需要从文件或数据库中读取包含姓名和电子邮件的记录 并将它们添加到现有的 Oulook 通讯组列表 来自私人联系人 而不是来自 GAL 我刚刚看到使用 LINQ to DASL 从 OL 读取邮件和约会的示例 但我不知道如何列出 dist
  • Bootstrap 表,空单元格中的破折号/连字符

    我正在使用Wenzhixin的bootstrap table模块 http bootstrap table wenzhixin net cn http bootstrap table wenzhixin net cn 当我使用 JSON 加
  • 在express.js中设置cookie出现j:前缀

    我正在尝试使用 res cookie 设置 cookie 如下所示 res cookie userId req user id set cookie here console log req user id returned correct
  • 将哈希锚定到页面底部

    转到页面 底部 的通用 HTML 锚标记是什么 我知道标签 会自动将用户带到页面顶部 但我不太确定页面底部 没有一个 不过 你可以用类似的东西来模拟它 a a 然后链接到 bottom 你可能会发现这个帖子 https stackoverf
  • 如何将 int 转换为一系列字符

    我正在尝试将 8 位微控制器 PIC 上的 C 整数分解为其 ASCII 等效字符 例如 将 982 转换为 9 8 2 到目前为止我想出的一切似乎都相当暴力 这是我现在基本上正在做的主要想法 if 10 lt n n lt 100 iso
  • Celery (Django) 速率限制

    我正在使用 Celery 来处理多个数据挖掘任务 其中一项任务连接到远程服务 该服务最多允许 10 个同时连接per user 或者换句话说 它CAN全球连接数超过 10 个 但CANNOT每个单独作业超过 10 个连接 I THINK 令
  • 权限被拒绝使用 Excel 12.0 库和 VB6 打开 Excel 文件

    我以前曾在 VB6 应用程序中多次使用 Excel 但从未遇到过如此奇怪的问题 试图完成一些非常简单的事情 我正在尝试打开 Excel xls 或 xlsx 文件并读取值 正如您可能看到的那样 当我尝试打开该文件时 收到错误 70 权限被拒
  • 将 CSV 文件内容与 filecmp 进行比较并忽略元数据

    import filecmp comparison filecmp dircmp dir local dir server comparison report full closure 我想将本地计算机上保存的所有 CSV 文件与服务器上保