문제

좋습니다. dat 파일을 바이트 배열로 읽고 있습니다.어떤 이유로 이러한 파일을 생성하는 사람들은 파일 끝에 약 0.5메가 정도의 쓸모 없는 널 바이트를 넣습니다.끝 부분을 다듬는 빠른 방법을 아는 사람이 있나요?

첫 번째 생각은 배열의 끝에서 시작하여 null이 아닌 다른 것을 찾을 때까지 뒤로 반복한 다음 해당 지점까지 모든 것을 복사하는 것이었지만 더 좋은 방법이 없는지 궁금합니다.

몇 가지 질문에 답하려면:파일 읽기 코드에 버그가 있는 것이 아니라 확실히 파일에 0바이트가 있다고 확신합니까?네, 저는 확신합니다.

모든 후행 0을 확실히 잘라낼 수 있습니까?예.

파일의 나머지 부분에 0이 있을 수 있나요?예, 0의 다른 자리가 있을 수 있으므로 아니요, 처음부터 시작하여 처음 0에서 멈출 수는 없습니다.

도움이 되었습니까?

해결책

이제 추가 질문에 대한 답변이 주어지면 근본적으로 옳은 일을하는 것처럼 들립니다. 특히, 마지막 0에서 파일의 모든 바이트를 터치하려면 0 만 있는지 확인해야합니다.

이제 모든 것을 복사 해야하는지 여부는 데이터를 사용하여 수행하는 일에 따라 다릅니다.

  • 아마도 인덱스를 기억하고 데이터 나 파일 이름으로 보관할 수 있습니다.
  • 데이터를 새 바이트 배열로 복사 할 수 있습니다.
  • 파일을 "수정"하려면 filestream.setlength 파일을 자르기 위해

"너 가지다 잘린 지점과 파일의 끝 사이의 모든 바이트를 읽는 것이 "중요한 부분입니다.

다른 팁

나는 Jon에 동의합니다. 중요한 비트는 마지막 바이트에서 최초의 비트가 아닌 바이트까지 바이트를 "터치"해야한다는 것입니다. 이 같은:

byte[] foo;
// populate foo
int i = foo.Length - 1;
while(foo[i] == 0)
    --i;
// now foo[i] is the last non-zero byte
byte[] bar = new byte[i+1];
Array.Copy(foo, bar, i+1);

나는 그것이 당신이 그것을 만들 수있는만큼 효율적이라고 확신합니다.

@factor Mystic,

가장 짧은 방법이 있다고 생각합니다.

var data = new byte[] { 0x01, 0x02, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00 };
var new_data = data.TakeWhile((v, index) => data.Skip(index).Any(w => w != 0x00)).ToArray();

이건 어때:

[Test]
public void Test()
{
   var chars = new [] {'a', 'b', '\0', 'c', '\0', '\0'};

   File.WriteAllBytes("test.dat", Encoding.ASCII.GetBytes(chars));

   var content = File.ReadAllText("test.dat");

   Assert.AreEqual(6, content.Length); // includes the null bytes at the end

   content = content.Trim('\0');

   Assert.AreEqual(4, content.Length); // no more null bytes at the end
                                       // but still has the one in the middle
}

0 = null을 가정하면 아마도 가장 좋은 방법입니다 ... 사소한 조정으로 사용하고 싶을 수도 있습니다. Buffer.BlockCopy 마침내 유용한 데이터를 복사 할 때 ..

테스트 :

    private byte[] trimByte(byte[] input)
    {
        if (input.Length > 1)
        {
            int byteCounter = input.Length - 1;
            while (input[byteCounter] == 0x00)
            {
                byteCounter--;
            }
            byte[] rv = new byte[(byteCounter + 1)];
            for (int byteCounter1 = 0; byteCounter1 < (byteCounter + 1); byteCounter1++)
            {
                rv[byteCounter1] = input[byteCounter1];
            }
            return rv;
        }

항상 LINQ 답변이 있습니다

byte[] data = new byte[] { 0x01, 0x02, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00 };
bool data_found = false;
byte[] new_data = data.Reverse().SkipWhile(point =>
{
  if (data_found) return false;
  if (point == 0x00) return true; else { data_found = true; return false; }
}).Reverse().ToArray();

배열 끝에서 0의 수를 계산하고 나중에 배열을 반복 할 때 길이 대신에 사용할 수 있습니다. 당신은 당신이 좋아하지만 이것을 캡슐화 할 수 있습니다. 요점은 실제로 새로운 구조로 복사 할 필요가 없다는 것입니다. 그들이 크면 그만한 가치가있을 수 있습니다.

파일에서 null 바이트가 유효한 값일 수 있는 경우 파일의 마지막 바이트는 null이 될 수 없다는 것을 알고 계십니까?그렇다면 뒤로 반복하여 null이 아닌 첫 번째 항목을 찾는 것이 가장 좋습니다. 그렇지 않은 경우 파일의 실제 끝이 어디에 있는지 알 수 있는 방법이 없습니다.

2바이트보다 긴 널 바이트 시퀀스(또는 유사한 제약 조건)가 있을 수 없는 등 데이터 형식에 대해 더 많이 알고 있는 경우.그러면 실제로 '전환점'에 대한 이진 검색을 수행할 수 있습니다.이는 선형 검색보다 훨씬 빠릅니다(전체 파일을 읽을 수 있다고 가정).

기본 아이디어(연속 null 바이트가 없다는 이전 가정을 사용)는 다음과 같습니다.

var data = (byte array of file data...);
var index = data.length / 2;
var jmpsize = data.length/2;
while(true)
{
    jmpsize /= 2;//integer division
    if( jmpsize == 0) break;
    byte b1 = data[index];
    byte b2 = data[index + 1];
    if(b1 == 0 && b2 == 0) //too close to the end, go left
        index -=jmpsize;
    else
        index += jmpsize;
}

if(index == data.length - 1) return data.length;
byte b1 = data[index];
byte b2 = data[index + 1];
if(b2 == 0)
{
    if(b1 == 0) return index;
    else return index + 1;
}
else return index + 2;

내 경우에는 linq 접근법이 끝나지 않았다 ^)))) 바이트 배열로 작동하는 것이 느려집니다!

얘들 아, 왜 array.copy () 메소드를 사용하지 않습니까?

    /// <summary>
    /// Gets array of bytes from memory stream.
    /// </summary>
    /// <param name="stream">Memory stream.</param>
    public static byte[] GetAllBytes(this MemoryStream stream)
    {
        byte[] result = new byte[stream.Length];
        Array.Copy(stream.GetBuffer(), result, stream.Length);

        return result;
    }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top