使用循环修改 byte[] 数组中的项目 (C#)

问题描述 投票:0回答:1

我从输入文件(ASCII 文本文件)中获得了一个 byte[] 数组,并且我正在尝试删除预设十六进制值的所有字节,而不将数组转换为 string 且不使用 lists .

这是我到目前为止想出的代码:

byte[] byteLine = File.ReadAllBytes(filePath);
byte lineBreak = (byte)0x0d;
int breakIndex = Array.IndexOf(byteLine, lineBreak);

这些是我认为需要的变量才能发挥作用。 Here我发现了一种方法,它的功能与我尝试执行的操作类似,因此我将代码(按原样)添加到项目中并尝试在循环中使用它。首先是一个 for 循环:

for(int i = 0; i < byteLine.Length; i++) {

    byte v = byteLine[i];
    if (v == lineBreak) {
    
        RemoveRange(byteLine, breakIndex, 2);
        
    }
}

我试图遍历数组中的每个字节,直到出现相当于换行符字节的字节,然后我尝试调用从换行符索引开始的方法 (breakIndex var) 删除 2 个字节(因为 ASCII 中的换行符使用 2 个字节 0d0a)。它应该循环遍历所有数组并对所有换行符重复此操作(lineBreak var)。这就是我认为如果我使用

for(;;)
循环它会做的事情,但它没有,我一定是做了错误。第二次尝试使用 foreach:

int t = breakIndex;
foreach (byte b in byteLine) {
if (b == lineBreak) {
        while (t != 0)
        {
            RemoveRange(byteLine, breakIndex, 2);
            t--;
        }
    }        
}

在第二个循环中,我添加了一个变量 (t) 用作“计数器”,其起始值等于换行符索引值 (breakIndex var)。我知道输入文件是一个方形 ASCII 图像,因此它的行数与换行符符号的数量相同(减去一个换行符,因为最后一行的最后一个字符不是换行符),因此循环应该循环等于换行次数的次数,或者直到 t 达到值 0,因为每次循环后它都会减少 1。此循环中存在同样的问题,该方法未触发。这是我尝试的第三件事,也是最后一件事:

int t = 0;
foreach (byte b in byteLine) {
    if (b == lineBreak) { do
        {
            RemoveRange(byteLine, breakIndex, 2);
            t++;
        }
        while (t < breakIndex); }
    }
}

与另一个 foreach 循环类似,但它是上升而不是下降,它应该继续循环,直到 t 变量达到换行符总数的值。我什至不知道我是否正确使用了 dowhile,这是我第一次尝试使用 do。这就是说,我在循环外测试了方法,它工作得很好,它只是删除了第一个换行符,因为它本身并不意味着循环。经过一番搜索,我找到了这个答案。

通过阅读该答案,我了解到应该有一种方法可以直接编辑 byte[] 数组中的项目,而无需很多解决方法,问题是我不知道如何将该解决方案应用于我的问题,因为我不熟悉使用那些 C# 函数。

c# arrays loops byte
1个回答
0
投票

这是就地处理数组的实现。

const byte CR = 0x0d, LF = 0x0a;

byte[] byteLine = [1, 2, 3, 4, CR, LF, 5, 6, 7, CR, LF, CR, LF, 8, 9];

int firstCR = Array.IndexOf(byteLine, CR);
if (firstCR >= 0) {
    // Jump to first CR
    int destination = firstCR, source = firstCR + 2;
    while (source < byteLine.Length) {
        if (byteLine[source] == CR) {
            source += 2;
        } else {
            byteLine[destination++] = byteLine[source++];
        }
    }
    // Fill remaining bytes with 0
    for (int i = destination; i < byteLine.Length; i++) {
        byteLine[i] = 0;
    }
}

但请注意,它远非单行代码,而且比像

byteLine.Where(b => b != lineBreak).ToArray()
这样的单行代码更可能包含错误。

此外,在不进行基准测试的情况下进行这样的优化是没有意义的。您认为可能很慢的解决方案有时比预期的要快。 Microsoft 在加速循环和 LINQ 查询方面投入了大量精力。

另请参阅:BenchmarkDotNet

© www.soinside.com 2019 - 2024. All rights reserved.