Frage

Ok, ich dat-Dateien in einen Byte-Array lese. Aus irgendeinem Grund, die Menschen, diese Dateien zu erzeugen setzen über den Wert eines halben meg nutzloser Null-Bytes am Ende der Datei. Jeder weiß, einen schnellen Weg, um diese aus dem Ende zu trimmen?

Erster Gedanke war am Ende des Feldes zu starten und rückwärts durchlaufen, bis ich etwas anderes als eine Null gefunden, kopieren Sie dann alles bis zu diesem Punkt, aber ich frage mich, ob es nicht ein besserer Weg.

einige Fragen zu beantworten: Sind Sie sicher, dass die 0 Byte auf jeden Fall in der Datei sind, anstatt es ein Fehler in der Datei Lesecode zu sein? Ja, ich bin sicher.

Können Sie definitiv alle nachgestellten 0s trimmen? Ja.

Kann es irgendwelche 0er in den Rest der Datei? Ja, es kann 0'en andere Orte sein, so, nein, ich nicht am Anfang und stoppe an den ersten 0 beginnen kann.

War es hilfreich?

Lösung

die zusätzliche Fragen jetzt beantwortet gegeben, es klingt wie Sie grundsätzlich das Richtige tun. Insbesondere haben Sie jedes Byte der Datei aus den letzten 0 weiter zu berühren, zu prüfen, ob es 0s nur hat.

Nun, ob Sie alles kopieren oder nicht, hängt davon ab, was Sie dann mit den Daten zu tun.

  • Sie könnten vielleicht den Index erinnern und sie mit den Daten oder Dateinamen halten.
  • Sie könnten die Daten in einen neuen Byte-Array kopieren
  • Wenn Sie möchten, um die Datei zu "reparieren", Sie nennen könnte? FileStream.SetLength die Datei

Die „Sie wird jedes Byte zwischen dem Abschneidepunkt und dem Ende der Datei zu lesen“ ist der kritische Teil though.

Andere Tipps

Ich stimme mit Jon. Die kritische Bit ist, dass Sie bis zum ersten Nicht-Null-Byte „berühren“ jedes Byte aus dem letzten müssen. So etwas wie folgt aus:

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);

Ich bin mir ziemlich sicher, das ist etwa so effizient wie Sie in der Lage sein werden es zu machen.

@Factor Mystic,

Ich denke, es gibt einen kürzesten Weg:

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();

Wie wäre es damit:

[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
}

Unter der Annahme, 0 = null, das ist wahrscheinlich die beste Wahl ... als Neben zwicken, könnte man Buffer.BlockCopy verwenden möchten, wenn Sie endlich die Nutzdaten kopieren ..

Test folgt aus:

    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;
        }

Es gibt immer eine LINQ Antwort

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();

Sie könnten nur die Anzahl der Null am Ende des Arrays zählen und dass anstelle von .Length verwenden, wenn später das Array iterieren. Man könnte dies einzukapseln wie Sie wollen. Hauptsache ist, die Sie nicht wirklich in eine neue Struktur kopieren müssen. Wenn sie groß sind, kann es sich lohnen.

, wenn in der Datei Null-Bytes gültige Werte sein kann, wissen Sie, dass das letzte Byte in der Datei nicht null sein kann. wenn ja, rückwärts iteriert und die Suche nach dem ersten Nicht-Null-Eintrag ist wahrscheinlich am besten, wenn nicht, dann gibt es keine Möglichkeit zu sagen, wo das eigentliche Ende der Datei ist.

Wenn Sie mehr über das Datenformat wissen, wie es keine Folge von Null-Bytes länger als zwei Bytes sein (oder einem ähnlichen Zwang). Dann können Sie in der Lage sein, tatsächlich für den ‚Übergangspunkt‘ eine binäre Suche. Dies sollte viel schneller als die lineare Suche sein (unter der Annahme, dass Sie in der gesamten Datei lesen können).

Die Grundidee (meine frühere Annahme über kein aufeinanderfolgende Null-Bytes verwendet wird), wäre:

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;

In meinem Fall LINQ Ansatz nie fertig ^))) Es ist zu langsam mit Byte-Arrays arbeiten!

Jungs, warum nicht Sie verwenden Array.Copy () Methode?

    /// <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;
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top