CSV_Spliter - разрезка больших CSV-файлов
Я несколько лет работал в электронном магазине http://digitalshop.ru/ и занимался там наполнением контента магазина с помощью пауков, приведением прайсов в единый формат и многими-многими подобными операциями по формированию базы магазина. Здесь я опубликую одну свою старинную утилитку из 2005-го года для работы с БОЛЬШИМИ прайс-листами. Столь большими, что их не получается откруть для редактирования или загрузить через WEB.
Эта утилита корректно разрезает большой прайс-лист на несколько маленьких.
Код никаких хитростей не имеет - он перед вами. В текущей версии я внес несколько модификаций и переделал обычную сортировку массива на сортировку с помощью LINQ (строка 137).
1: Module Module1
2:
3: Sub Main()
4: Dim PRM() As String = Environment.GetCommandLineArgs
5: Dim Num As Integer = 2
6: Dim Encode1 As System.Text.Encoding = Text.Encoding.GetEncoding(1251)
7: Try
8: For Each One As String In PRM
9: 'оттобрали в параметрах хелп
10: If One.ToLower.Contains("-help") Or One.ToLower.Contains("/help") Or One.ToLower.Contains("/h") Or One.ToLower.Contains("-h") Then
11: Console.WriteLine("ParseParm: Help request.")
12: GoTo Usage
13: End If
14: Next
15: For Each One As String In PRM
16:
17: If One.StartsWith("-") Then
18: If IsNumeric(One.Replace("-", "").Trim) Then
19: 'отобрали на сколько частей разбиваем CSV файл
20: Num = CInt(One.Replace("-", "").Trim)
21: Else
22: 'кодировка входного и выходного файла
23: Select Case One.ToLower
24: Case "ascii"
25: Encode1 = Text.Encoding.GetEncoding(1251)
26: Case "utf8"
27: Encode1 = Text.Encoding.UTF8
28: Case "unicode"
29: Encode1 = Text.Encoding.Unicode
30: Case Else
31: Console.WriteLine("ParseParm: Encode not parse.")
32: GoTo Usage
33: End Select
34: End If
35: End If
36: Next
37: 'выясним имя рабочего файла
38: Dim FullFileName As String = ""
39: For Each One As String In PRM
40: If Not One.StartsWith("-") Then
41: If Not One.ToLower.Contains("csv_spliter") And Not One.ToLower.Contains("exe") Then
42: If Not GetWorkFile(One, FullFileName) Then
43: Console.WriteLine("ParseParm: Default filename.")
44: GoTo Usage
45: Else
46: 'имя задано в параметрах - его вернул GetWorkFile
47: GoTo SetFile
48: End If
49: End If
50: End If
51: Next
52: 'имя не задано - рабочий каталог по умолчанию
53: If Not GetWorkFile(My.Application.Info.DirectoryPath, FullFileName) Then
54: Console.WriteLine("WorkFile :" & FullFileName)
55: GoTo Usage
56: End If
57: SetFile:
58: If My.Computer.FileSystem.FileExists(FullFileName) Then
59: Console.WriteLine("Spliting " & FullFileName & " (" & Encode1.ToString.Replace("System.Text.", "") & ") " & " on " & Num & " slice. ")
60: Console.WriteLine("Please wait...")
61: Else
62: Console.WriteLine("WorkFile :" & FullFileName & " not found.")
63: GoTo Usage
64: End If
65: '
66: 'есть входной файл и все параметры
67: '
68: Dim AllData As String = My.Computer.FileSystem.ReadAllText(FullFileName, Encode1)
69: Dim RDR1 As New IO.StringReader(AllData)
70: Dim Head As String = RDR1.ReadLine()
71: Dim Str1 As String = ""
72: Dim LineCount As Integer = 0
73: 'не более 100 миллионов строк
74: For i As Integer = 1 To 100000000
75: Str1 = RDR1.ReadLine
76: If Str1 Is Nothing Then
77: Exit For
78: Else
79: 'в первом проходе посчитаем количество строк
80: LineCount += 1
81: End If
82: Next
83: RDR1.Close()
84: 'теперь основной проход с копированием
85: Dim RDR2 As New IO.StringReader(AllData)
86: RDR2.ReadLine()
87: Dim LineInSlice As Integer = LineCount \ Num
88: Dim NewFileName As String = ""
89: Dim LineNumber As Integer = 2
90: Dim StartLineNumber As Integer = 0
91: For SliceNum As Integer = 1 To Num
92: If SliceNum = Num Then
93: 'последний слайс до конца
94: StartLineNumber = LineNumber
95: Dim Out2 As New Text.StringBuilder()
96: Out2.AppendLine(Head)
97: For i As Integer = 1 To LineCount
98: Dim CurLine As String = ""
99: LineNumber += 1
100: CurLine = RDR2.ReadLine
101: If CurLine Is Nothing Then Exit For
102: Out2.AppendLine(CurLine)
103: Next
104: NewFileName = FullFileName.Replace(".csv", "-" & SliceNum & ".csv")
105: My.Computer.FileSystem.WriteAllText(NewFileName, Out2.ToString, False, Encode1)
106: Console.WriteLine("Write " & NewFileName & ", Line " & StartLineNumber & "-" & LineNumber - 1)
107: Else
108: StartLineNumber = LineNumber
109: Dim Out1 As New Text.StringBuilder()
110: Out1.AppendLine(Head)
111: For i As Integer = 0 To LineInSlice
112: LineNumber += 1
113: Out1.AppendLine(RDR2.ReadLine)
114: Next
115: NewFileName = FullFileName.Replace(".csv", "-" & SliceNum & ".csv")
116: My.Computer.FileSystem.WriteAllText(NewFileName, Out1.ToString, False, Encode1)
117: Console.WriteLine("Write " & NewFileName & ", Line " & StartLineNumber & "-" & LineNumber - 1)
118: End If
119: Next
120: RDR2.Close()
121: Exit Sub
122:
123: Catch ex As Exception
124: Console.WriteLine("Error: " & ex.Message)
125: Console.ReadLine()
126: GoTo Usage
127: End Try
128: Usage:
129: Console.WriteLine(PRM.Count.ToString & ", " & My.Application.Info.DirectoryPath)
130: Console.WriteLine("Usage: CSV_Spliter.exe [-Num] [-ACSII/Unicode/UTF8] [FileName/DirectoryName] [/help] [-help] [/h] [-h]" & vbCrLf & _
131: " This program splitting large CSV file " & vbCrLf & _
132: "Num: Number on CSV segment, default 2" & vbCrLf & _
133: "Encode: ACSII or Unicode or UTF8 - input and output CSV encoding, default codepage 1251" & vbCrLf & _
134: "FileName: Defaul last creating file in working directory.")
135:
136: Exit Sub
137: End Sub
138:
139: Function GetWorkFile(ByVal Parm As String, ByRef FullFileName As String) As Boolean
140: Try
141: If IO.Path.GetExtension(Parm) = "" Then
142: 'задан только каталог - ищем последний созданный CSV-Файл
143: Dim WorkDir As IO.DirectoryInfo = My.Computer.FileSystem.GetDirectoryInfo(Parm)
144: If WorkDir.GetFiles("*.csv").Count = 0 Then
145: Console.WriteLine("GetWorkFile: No *.csv files in direcory " & Parm)
146: FullFileName = ""
147: Return False
148: Else
149: Dim FileList() As IO.FileInfo = WorkDir.GetFiles("*.csv")
150: Dim OrderedList = (From X In FileList Select X Where X.Extension.ToLower = ".csv" Order By X.CreationTime Descending).First
151: Dim LastCSV As String = OrderedList.Name
152: FullFileName = IO.Path.Combine(Parm, LastCSV)
153: Return True
154: End If
155: ElseIf IO.Path.GetExtension(Parm).ToLower = ".csv" Then
156: 'задан CSV -файл
157: If IO.Path.GetDirectoryName(Parm) = "" Then
158: 'задано только имя файла
159: FullFileName = IO.Path.Combine(My.Application.Info.DirectoryPath, Parm)
160: Return True
161: Else
162: 'задано полное имя - диретория+файл
163: FullFileName = Parm
164: Return True
165: End If
166: Else
167: 'расширение файла есть, но не CSV
168: Console.WriteLine("GetWorkFile: Extensions " & IO.Path.GetExtension(Parm).ToLower)
169: FullFileName = ""
170: Return False
171: End If
172:
173: Catch ex As Exception
174: Console.WriteLine("Error in GetWorkFile: " & ex.Message)
175: Console.ReadLine()
176: FullFileName = ""
177: Return False
178: End Try
179:
180: End Function
181:
182: End Module
Сгрузить утилиту CSV_Spliter в откомпилированном виде можно отсюда.
Comments (
)
Link to this page:
//www.vb-net.com/CSV_Spliter/index.htm
|