3

由于某些原因,我想将一个 GUID 作为 ID 写入一个文件以保存,并在打开文件之前删除该 ID。

 static void Main(string[] args)
    {
        string id = "b669fd8c904d48e0945c16cac1dc5ed9";
        byte[] idbyte = UnicodeEncoding.Default.GetBytes(id);

        FileStream input = new FileStream(@"C:\test.xlsx", FileMode.Open, FileAccess.Read);
        FileStream output = new FileStream(@"C:\test1.xlsx", FileMode.OpenOrCreate, FileAccess.Write);
        CopyStream(input, output);
        // add id with byte[] at the end of the file
        output.Write(idbyte, 0, idbyte.Length);
        output.Close();
        input.Close();

        FileStream input1 = new FileStream(@"C:\test1.xlsx", FileMode.Open, FileAccess.Read);
        FileStream output1 = new FileStream(@"C:\test2.xlsx", FileMode.OpenOrCreate, FileAccess.Write);
        int SizeOfBuffer = 1024 * 16;
        try
        {

            byte[] buffer = new byte[SizeOfBuffer];
            byte[] bufferLast = new byte[SizeOfBuffer];
            int read;
            int Nextread;
            while ((read = input1.Read(buffer, 0, buffer.Length)) > 0)
            {

                if ((Nextread = input1.Read(bufferLast, 0, buffer.Length)) > 0)
                {
                    output1.Write(buffer, 0, read);
                    output1.Write(bufferLast, 0, Nextread);
                }
                else   // delete id with byte[] 
                {

                    byte[] buffer2 = new byte[SizeOfBuffer];
                    for (int i = 0; i < read - idbyte.Length; i++)
                    {
                        buffer2[i] = buffer[i];
                    }
                    output1.Write(buffer2, 0, buffer2.Length);
                    break;
                }

            }


        }
        catch (Exception ex)
        {

            Console.WriteLine(ex.ToString());
        }
        output1.Close();
        input1.Close();
        Console.ReadLine();
    }

  private static void CopyStream(Stream input, Stream output)
    {
        int SizeOfBuffer = 1024 * 16;
        try
        {
            byte[] buffer = new byte[SizeOfBuffer];
            int read;
            while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                output.Write(buffer, 0, read);
            }
        }
        catch (Exception ex)
        {

            Console.WriteLine(ex.ToString());
        }
    }

但是当我打开 C:\test2.xlsx 时,excel 显示错误:“Excel 在 'test2.xlsx' 中发现不可读的内容”!

如何解决这个问题呢 ?

4

2 回答 2

0

以下对我有用。如您所见,我进行了一些重组,以便更轻松地了解我在做什么并简化测试。如果您有任何问题,请告诉我。

class Program
{
    private const int SIZE_OF_BUFFER = 1024 * 16;
    private const string FILE_PATH_ORIGINAL = @"C:\test.xlsx",
                        FILE_PATH_WithId = @"C:\test1.xlsx",
                        FILE_PATH_IdRemoved = @"C:\test2.xlsx";

    private static readonly byte[] idbyte = UnicodeEncoding.Default.GetBytes("b669fd8c904d48e0945c16cac1dc5ed9");

    static void Main(string[] args)
    {
        AddGuidToFile(FILE_PATH_ORIGINAL, FILE_PATH_WithId);
        RemoveGuidToFile(FILE_PATH_WithId, FILE_PATH_IdRemoved);
        CompairFiles(FILE_PATH_ORIGINAL, FILE_PATH_IdRemoved);

        Console.ReadLine();
    }

    private static void AddGuidToFile(string sourceFilePath, string destinationFilePath)
    {
        byte[] buffer = new byte[SIZE_OF_BUFFER];
        FileStream input = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read),
                    output = new FileStream(destinationFilePath, FileMode.OpenOrCreate, FileAccess.Write);
        int read;

        try
        {
            while ((read = input.Read(buffer, 0, buffer.Length)) > 0)   //Copy source file to destination file.
            {
                output.Write(buffer, 0, read);
            }

            output.Write(idbyte, 0, idbyte.Length);                     //Add guid to the end of the destination file.
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
        finally
        {
            //Close files
            input.Close();
            output.Close();
        }
    }

    private static void RemoveGuidToFile(string sourceFilePath, string destinationFilePath)
    {
        byte[] currentBuffer = new byte[SIZE_OF_BUFFER],
                nextBuffer = new byte[SIZE_OF_BUFFER],
                tempBuffer;
        FileStream input = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read),
                    output = new FileStream(destinationFilePath, FileMode.OpenOrCreate, FileAccess.Write);
        int currentRead,
            nextRead = 0;                                       //Initialize to 0 incase file's lenght is less then SizeOfBuffer.

        try
        {
            currentRead = input.Read(currentBuffer, 0, currentBuffer.Length);   //Get first chunk.
            if (currentRead == currentBuffer.Length)                            //If first chunck is a full buffer then loop until it is not.
            {
                nextRead = input.Read(nextBuffer, 0, nextBuffer.Length);

                while (nextRead > idbyte.Length)
                {
                    output.Write(currentBuffer, 0, currentRead);                //Since nextBuffer is large enough to contain the ID, write the current buffer out.

                    //Swap buffers.
                    tempBuffer = currentBuffer;
                    currentBuffer = nextBuffer;
                    nextBuffer = tempBuffer;

                    //Update counts and fill next buffer.
                    currentRead = nextRead;
                    nextRead = input.Read(nextBuffer, 0, nextBuffer.Length);
                }
            }

            currentRead += nextRead - idbyte.Length;                            //Update currentRead to be the number of bytes in the buffer which are not part of the ID.

            output.Write(currentBuffer, 0, currentRead);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
        finally
        {
            //Close files
            input.Close();
            output.Close();
        }
    }

    private static void CompairFiles(string originalFilePath, string idRemovedFilePath)
    {
        byte[] originalBuffer = new byte[SIZE_OF_BUFFER],
                idRemovedBuffer = new byte[SIZE_OF_BUFFER];
        FileStream original = new FileStream(originalFilePath, FileMode.Open, FileAccess.Read),
                    idRemoved = new FileStream(idRemovedFilePath, FileMode.Open, FileAccess.Read);
        int originalRead,
            idRemovedRead;

        try
        {
            do
            {
                originalRead = original.Read(originalBuffer, 0, originalBuffer.Length);
                idRemovedRead = idRemoved.Read(idRemovedBuffer, 0, idRemovedBuffer.Length);

                if (originalRead != idRemovedRead) { throw new Exception("Error: file sizes do not match.  originalRead = " + originalRead + ", idRemovedRead = " + idRemovedRead + ", SIZE_OF_BUFFER = " + SIZE_OF_BUFFER); }

                for (int i = 0; i < originalRead; i++)
                {
                    if (originalBuffer[i] != idRemovedBuffer[i]) { throw new Exception("Error: file contents do not match.  i = " + i + ",inputBuffer[i] = " + originalBuffer[i] + ", idRemovedBuffer[i] = " + idRemovedBuffer[i]); }
                }
            }
            while (originalRead == idRemovedRead && originalRead > 0);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
        finally
        {
            //Close files
            original.Close();
            idRemoved.Close();
        }
    }
}
于 2012-12-13T03:56:35.477 回答
0

带有扩展名的 Excel 文件xlsx(注意末尾的“x”)实际上是zip包含xml文档的文件。如果您将数据添加到文件末尾,则会使 zip 无效,因此 Excel 无法打开它。

看起来您的函数可能没有正确删除添加的文本。您可以尝试在十六进制比较程序中打开原始文件和新文件,看看它们有什么不同。此外,您可以将文件重命名为“.zip”以查看它是否在 zip 程序中打开。

于 2012-12-13T03:56:47.037 回答