c# - 为什么这个拆分/合并程序在 .txt 中表现良好但在 .jpg 中表现不佳
问题描述
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Homework
{
class Program
{
static void Main(string[] args)
{
string mode = args[0];
string name = args[1];
if(mode == "split")
{
FileInfo fileinfo = new FileInfo(name);
int fileSize = (int)fileinfo.Length;
int partSize = 1024;
int numberOfPart = (int)Math.Ceiling((double)fileSize / partSize);
string chunkName = "";
int byteRemaining = fileSize;
FileStream list = File.OpenWrite(name + "_list");
StreamWriter list_write = new StreamWriter(list, System.Text.Encoding.UTF8);
list_write.WriteLine(name); //list 파일 첫 줄에 원본 파일 이름 저장
Console.WriteLine(name + "_list");
for(int count = 1; count <= numberOfPart; count++)
{
byte[] buffer = new byte[partSize];
chunkName = string.Format("{0}_{1}", name, count);
int chunkSize;
FileStream origin = File.OpenRead(name);
BinaryReader origin_read = new BinaryReader(origin);
if(byteRemaining >= partSize)
{
chunkSize = partSize;
}
else
{
chunkSize = byteRemaining;
}
buffer = origin_read.ReadBytes(chunkSize); //원본 읽기
FileStream chunk = File.OpenWrite(chunkName);
BinaryWriter chunk_write = new BinaryWriter(chunk);
chunk_write.Write(buffer); //chunk에 쓰기
byteRemaining -= chunkSize;
list_write.WriteLine(chunkName); //chunkName도 list 파일에 저장
Console.WriteLine(chunkName);
origin_read.Close();
chunk_write.Close();
}
list_write.Close();
}
else if(mode == "merge")
{
FileStream list = File.OpenRead(name); //list 파일 읽는 스트림
StreamReader list_read = new StreamReader(list, Encoding.Default, true);
string originName = list_read.ReadLine();
FileStream origin = File.OpenWrite(originName); //origin 파일 다시 만드는 스트림
BinaryWriter origin_write = new BinaryWriter(origin);
int partSize = 1024;
while(list_read.EndOfStream == false) //list 파일이 끝날때까지 읽어들임
{
string chunkName = list_read.ReadLine();
byte[] buffer = new byte[partSize];
FileStream chunk = File.OpenRead(chunkName); //각 chunk 읽는 스트림
BinaryReader chunk_read = new BinaryReader(chunk);
FileInfo fileinfo = new FileInfo(chunkName);
buffer = chunk_read.ReadBytes((int)fileinfo.Length); //파일 크기만큼 buffer로 읽어옴
origin_write.Write(buffer); //buffer로 옮긴 내용 원본파일에 쓰기
}
}
Console.ReadKey();
}
}
}
*预期的
- split : 将文件分割成 1kb 的块,并制作 [filename]_list 文件,其中包含原始文件名和块名的信息([filename]_1, [filename]_2 . . .)
- 合并:读取在拆分过程中创建的 [filename]_list 文件并再次合并一个文件。合并后,合并后的文件必须与我们上面拆分的原始文件完全相同。
*问题
- 在 .txt 文件的情况下 -> 按预期表现良好,但在 .jpg 文件中,拆分良好但合并文件与原始文件不同。
解决方案
问题:
您的代码的问题是,当您将文件拆分为部分/部分时,而不是将文件拆分为单独的文件,每个文件都包含下一个字节的部分,您每次都从头开始拆分文件,导致错误合并文件(演示问题的图像)
解决方案:
因此,您只需移出for loop
3 行特定的代码,使您的代码如下所示:
FileStream origin = File.OpenRead(name); // 1st line
BinaryReader origin_read = new BinaryReader(origin); // 2nd line
for (int count = 1; count <= numberOfPart; count++)
{
...
}
origin_read.Close(); //3rd line
list_write.Close();
推荐解决方案:
虽然,这里也是推荐的解决方案。
using System;
using System.IO;
using System.Linq;
namespace Homework
{
class Program
{
static void Main(string[] args)
{
string mode = args[0];
string file = args[1]; // sourcefile or sourcefile_list
try{
switch (mode){
case "split":
byte[] buffer = File.ReadAllBytes(file);
int partSize = 1024;
int numberOfPart = (int)Math.Ceiling((double)buffer.Length / partSize);
string chunkPathName; // The path-and-name of the chunk-file
// go through all parts
for (int count = 0; count < numberOfPart; count++)
{
chunkPathName = file + "_" + (count + 1);
//write all bytes to the destination-chunk file from a specific point and on.... and then "pass"/write the chuck's path-name into the _list file
File.WriteAllBytes(chunkPathName, buffer.Skip(count * partSize).Take(partSize).ToArray());
File.AppendAllText(file + "_list", chunkPathName + "\n");
Console.WriteLine("Splitting: " + chunkPathName);
}
break; // exit switch
case "merge":
// create a stream pointing to your desired-destination/origin-file
var originstream = new FileStream(file.Remove(file.Length - "_list".Length, "_list".Length), FileMode.Create);
Console.WriteLine("destination path = " + file.Remove(file.Length - "_list".Length) + "\n");
// go through each line of the file (_list)
foreach (string _chunkPathName in File.ReadAllLines(file))
{
Console.WriteLine("Merging: " + _chunkPathName);
// read all bytes from chunk and append them into the origin-file
byte[] chunk = File.ReadAllBytes(_chunkPathName);
originstream.Write(chunk, 0, chunk.Length);
}
// close the stream
originstream.Close();
break; // exit switch
}
Console.WriteLine("\n" + mode + " is done!");
}catch (Exception ex){
//code for any other type of exception
}
Console.ReadKey();
}
}
}
我也试图用评论说得足够清楚..
推荐阅读
- pandas - 使用 DataFrame.assign 创建多个新的 DataFrame 列并应用
- python-3.x - 线性规划:在 PYTHON 中使用 DocPlex 生成的所有解决方案的列表(使用 cplex 解决方案池失败)?
- c# - C#和Arduino之间通过蓝牙通信,接收到奇怪的数据
- docker - 高山图像中的 Crontab
- mysql - 如何在 SQL 脚本中声明变量?
- android - Kotlin android 从广播接收器中检索应用程序
- postgresql - 具有高共享读取的 postgreSQL 慢查询
- jhipster - jhipster-registry:spring cloud config conf with ssh throws 不是有效的私钥
- asp.net - .NET 5.0 React SPA 在 Debug 中工作,但在发行版中不工作
- rest - Wiremock 优先级与场景