今日は、新旧2つのテキストファイルの差分ファイルを作成する方法を試してみました。
ここで言う2つのテキストファイルとは、全く別物ではなく、旧テキストファイルに追記していったものが新テキストファイルとなっています。
通常、Ruby で差分ファイルを作成しようと考えた場合、以下のようになると思います。
1
2
| file_diff.puts open( file_new, "r" ).readlines
- open( file_old, "r" ).readlines
|
しかし、当方で検証してみた結果、以下のデメリットを確認しました。
- 読み込んだ2つのテキストファイルの内容を配列に確保するため、大サイズのテキストファイルだとメモリエラーになる。
- 空白行が削除されてしまう(上記のスクリプトの場合だけ?)
というわけで、テキストファイルを1行ずつ読み込んで差分ファイルを作成する方法を試行!
処理手順概要
- 旧テキストファイルの行数をカウント
新テキストファイルを順次読み込む
旧テキストファイルの行数分は読み飛ばし
- 旧テキストファイルの行数分より後ろの行は差分ファイルへ書き込む
※2つのファイルを同時に1行ずつ読んで双方を比較する方法もありますが、数万行レベルになると処理が遅くなるし、新テキストファイルが旧テキストファイルに追記した形になっていると最初からわかっているので、読み飛ばす方法を採っています。
Ruby スクリプト
参考までに、今回の検証で使用した Ruby スクリプトです。
※検証環境は、Windows XP (SP3) + Ruby 1.9.2-p290 です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
| # -*- coding: utf-8 -*-
#
# 新旧2つのテキストファイルの差分ファイルを作成
#
# date name version
# 2011.11.19 mk-mode 1.00 新規作成
#
# Copyright(C)2011 mk-mode.com All Rights Reserved.
#--------------------------------------------------
#++
class DiffText
# 定数
FILE_OLD = "D:\\work\\file_old.txt"
FILE_NEW = "D:\\work\\file_new.txt"
FILE_DIFF = "D:\\work\\file_diff.txt"
# [CLASS] 差分作成処理
class Diff
# INTIALIZE
def initialize
# 各種件数
@cnt_old = 0
@cnt_new = 0
@cnt_diff = 0
end
# 行数取得 ( FILE_OLD )
def get_linecount_old
begin
# ファイルOPEN
file_old = open( FILE_OLD, "r" )
while line = file_old.gets
@cnt_old += 1
end
puts "LINE COUNT ( OLD ) = #{@cnt_old}"
ensure
# FILE CLOSE ( 意図的に )
file_old.close
end
end
# 差分ファイル作成
def make_diff_file
begin
# ファイルOPEN
file_new = open( FILE_NEW, "r" )
file_diff = open( FILE_DIFF, "w" )
while line = file_new.gets
@cnt_new += 1
unless @cnt_new > @cnt_old
next
else
@cnt_diff += 1
file_diff.puts( line )
end
end
puts "LINE COUNT ( NEW ) = #{@cnt_new}"
puts "LINE COUNT ( DIFF ) = #{@cnt_diff}"
ensure
# FILE CLOSE ( 意図的に )
file_new.close
file_diff.close
end
end
end
#### MAIN ####
# インスタンス化 ( 差分ファイル作成処理クラス )
obj_diff = Diff.new
# 行数取得 ( 旧ファイル )
obj_diff.get_linecount_old
# 差分ファイル作成
obj_diff.make_diff_file
end
|
これでメモリエラーは発生しなくなりました。
応用したいと思っている処理に適用してみることにします。
以上。