Лучший способ объединить простые текстовые файлы?
У меня есть целая куча простых текстовых файлов, названных следующим образом: file1.txt, file2.txt, ..., file14.txt, ... Я хочу объединить их все в правильном порядке в один файл.txt. Как мне сделать это программно? Пакетный файл работает в командном окне? Или написать консольное приложение Windows?
В любом случае, могу ли я получить код? Благодарю.
Больше информации:
большое количество файлов. Сотня или больше каждый раз, когда я делаю этот отчет.
dir не даст файлы в правильной последовательности: например, file10.txt появляется перед file2.txt, поэтому я делаю упор. Кажется, для i от 1 до n конкатенированный с префиксом имени файла является лучшим. Но я не знаю, как это сделать в пакетном режиме или выполнить команду из программы Windows.
Я склоняюсь к созданию консольного приложения Windows. Будет ли что-то подобное работать?
class Program
{
static void Main(string[] args)
{
string strCmdLine;
System.Diagnostics.Process process1;
process1 = new System.Diagnostics.Process();
Int16 n = Convert.ToInt16(args[1]);
int i;
for (i = 1; i < n; i++)
{
strCmdLine = "/C copy more work here " + args[0] + i.ToString();
System.Diagnostics.Process.Start("CMD.exe", strCmdLine);
process1.Close();
}
}
}
7 ответов
Это должно хорошо работать, если вы готовы потратить минимум времени. Для полностью автоматизированного процесса вам необходимо определить количество файлов (что не так сложно, но я здесь опущен). Но для всего 20 отчетов это, вероятно, должно подойти.
Кроме того, процесс в командном файле не является оптимальным. На самом деле это ужасно. Я думаю, что это O(n!). Вероятно, намного лучше использовать версию под командным файлом.
Как командный файл:
@echo off
if not "%~1"=="" goto begin
echo Usage: %~n1 ^<N^>
echo where ^<N^> is the highest number that occurs in the file name.
goto :eof
:begin
set N=%~1
rem create empty file
copy nul temp.txt
rem just loop from 1 to N
for /l %%x in (1,1,%N%) do call :concat %%x
rename temp.txt result.txt
goto :eof
:concat
copy temp.txt+file%1.txt temp2.txt
move /y temp2.txt temp.txt
goto :eof
Не проверено, но это довольно просто, поэтому я сомневаюсь, что в нем слишком много ошибок.
В качестве альтернативы я просто подумал, что следующее будет работать еще проще (в командной строке):
(for /l %x in (1,1,N) do type file%x.txt) > result.txt
Просто замени N
с самым высоким суффиксом у вас есть.
Не самый эффективный код, но у вас должна получиться идея:
Dim files As String()
Dim tempFile As String
Dim orderedFiles As New Dictionary(Of Int32, String)
Dim fileNumber As Int32
Dim filePos As Int32
Dim dotTxtPos As Int32
Dim fileData As String
Const CONST_DEST_FILE As String = "c:\tempfiles\destination.txt"
files = System.IO.Directory.GetFiles("c:\tempfiles", "file*.txt")
For Each tempFile In files
If tempFile.ToLower.Contains("\file") = False Or tempFile.ToLower.Contains(".txt") = False Then
Continue For
End If
filePos = tempFile.ToLower.IndexOf("\file") + 5
dotTxtPos = tempFile.ToLower.IndexOf(".txt", filePos)
If Int32.TryParse(tempFile.ToLower.Substring(filePos, dotTxtPos - filePos), fileNumber) = True Then
orderedFiles.Add(fileNumber, tempFile)
End If
Next
If System.IO.File.Exists(CONST_DEST_FILE) = True Then
System.IO.File.Delete(CONST_DEST_FILE)
End If
fileNumber = 0
Do While orderedFiles.Count > 0
fileNumber += 1
If orderedFiles.ContainsKey(fileNumber) = True Then
tempFile = orderedFiles(fileNumber)
fileData = System.IO.File.ReadAllText(tempFile)
System.IO.File.AppendAllText(CONST_DEST_FILE, fileData)
orderedFiles.Remove(fileNumber)
End If
Loop
Если вы работаете в Windows, установите Cygwin, чтобы иметь оболочку bash, а затем:
для меня в {1..N}; do cat ${1}.txt >> all.txt; сделанный
Где N - это количество файлов, которые у вас есть. Все файлы будут объединены в all.txt.
Это можно сделать с помощью следующей оболочки Windows PowerShell на одну строку (для удобства чтения она разделена на четыре строки):
Get-ChildItem -Filter "*.txt" |
Sort-Object { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20) }) } |
gc |
sc result.txt
Get-ChildItem
извлекает имена файлов, но они будут в неправильном порядке (отсортированы ASCII бетически, а не по алфавиту).
Sort-Object
Командлет используется для сортировки имен файлов, как вы указали, добавляя числа в имени файла перед сравнением имен.
gc
это псевдоним для Get-Content
, который читает содержимое всех входных файлов.
sc
это псевдоним для Set-Content
, который записывает результат в указанный файл.
Вот альтернативный подход с использованием C#, если вы не можете / не будете использовать PowerShell:
static class Program
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
static extern int StrCmpLogicalW(string s1, string s2);
static void Main()
{
string[] files = Directory.GetFiles(@"C:\Path\To\Files", "*.txt");
Array.Sort(files, StrCmpLogicalW);
File.WriteAllLines("result.txt", files.SelectMany(file => File.ReadLines(file)));
}
}
Это использует StrCmpLogicalW
функция, чтобы получить имена файлов в правильном порядке (эта функция на самом деле то, что Windows Explorer использует для сортировки имен файлов).
У вас есть несколько возможностей. Если вы делаете dir
в командной строке, и они отображаются в нужном вам порядке, все довольно просто - вы можете сделать что-то вроде:
copy file*.txt destination.txt
Это будет иметь несколько незначительных побочных эффектов - это остановит чтение любого файла при первом control-Z
он встречает, и он добавит control-Z
в конец файла. Если вы не хотите, чтобы это произошло, вы можете добавить /b
:
copy /b file*.txt destination.txt
Если "каталог" не тот порядок, который вы хотите, то вы можете сделать что-то вроде:
for %c in (a.txt b.txt c.txt) copy destination.txt+%c
где a.txt
, b.txt
, c.txt
(и т. д.) - это файлы, которые вы хотите скопировать, перечислены в том порядке, в котором вы хотите их скопировать (и, очевидно, destination.txt
это имя, которое вы хотите дать результат, где вы собрали их все вместе. Кроме того, вы можете перечислить их все в одной командной строке, как copy a.txt+b.txt+c.txt destination.txt
,
В командной строке вы можете выполнить,type *.txt > destination.txt
Примечание: это также объединяет текстовые файлы в подкаталогах
Я помню одну очень полезную программу: split & concat. для Mac OS X... не знаю, была ли другая версия ОС... работает! http://loekjehe.home.xs4all.nl/Split&Concat/