إزالة زائدة بالقيم الخالية من صفيف بايت في C#

StackOverflow https://stackoverflow.com/questions/240258

  •  04-07-2019
  •  | 
  •  

سؤال

حسنا ، أنا أقرأ في dat الملفات إلى صفيف بايت.لسبب ما, الناس الذين توليد هذه الملفات وضع حوالي نصف ميغ يستحق عديمة الفائدة بايت فارغة في نهاية الملف.هل من أحد يعرف طريقة سريعة لخفض هذه النهاية ؟

كان يعتقد في البداية أن تبدأ في نهاية مجموعة وأعاد إلى الوراء حتى وجدت شيئا آخر غير فارغة ، ثم نسخ كل شيء حتى تلك النقطة ، ولكن أتساءل إذا لم يكن هناك طريقة أفضل.

للإجابة على بعض الأسئلة:هل أنت متأكد من 0 بايت بالتأكيد في الملف بدلا من أن يكون هناك خطأ في قراءة ملف التعليمات البرمجية ؟ نعم أنا متأكد من ذلك.

يمكنك بالتأكيد تقليم جميع زائدة 0s?نعم.

يمكن أن يكون هناك أي 0s في بقية الملف ؟ نعم ، يمكن أن يكون هناك 0 أماكن أخرى, حتى, لا, أنا لا يمكن أن تبدأ في بداية تتوقف عند أول 0.

هل كانت مفيدة؟

المحلول

إعطاء المزيد من الأسئلة الآن أجاب: يبدو أنك في الأساس تفعل الشيء الصحيح.وعلى وجه الخصوص ، يجب أن تلمس كل بايت من الملف من الماضي 0 فصاعدا ، للتحقق من أن لديه 0s.

الآن, إذا كان لديك لنسخ كل شيء أو لا يعتمد على ما كنت ثم القيام مع البيانات.

  • ربما كنت يمكن أن نتذكر مؤشر والحفاظ عليه مع البيانات أو اسم الملف.
  • يمكنك نسخ البيانات إلى صفيف بايت
  • إذا كنت ترغب في "إصلاح" الملف, يمكنك الاتصال FileStream.SetLength إلى اقتطاع الملف

"أنت لديك لقراءة كل بايت بين اقتطاع نقطة نهاية الملف" هو جزء هام على الرغم من.

نصائح أخرى

وأنا أتفق مع جون. بت الحاسم هو أنه يجب أن "تلمس" كل بايت من آخر واحد حتى أول بايت غير صفرية. شيء من هذا القبيل:

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 الصوفي،

وأعتقد أن هناك وسيلة أقصر:

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 = فارغة، وهذا هو على الأرجح أفضل رهان ... كما قرص طفيفة، قد ترغب في استخدام 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();

هل يمكن الاعتماد فقط على عدد من الصفر في نهاية المصفوفة واستخدام ذلك بدلا من. طول عندما بالتكرار مجموعة في وقت لاحق. هل يمكن أن تلخص هذه كيفما تشاء. النقطة الرئيسية هي لا تحتاج حقا لنسخه في الهيكل الجديد. إذا كانت كبيرة، قد يكون من يستحق ذلك.

وإذا كان في ملف بايت فارغة يمكن أن يكون القيم الصالحة، هل تعرف أن البايت الأخير في الملف لا يمكن أن تكون فارغة. إذا كان الأمر كذلك، بالتكرار إلى الوراء، وتبحث عن أول دخول غير الصفرية هو على الارجح أفضل، إن لم يكن ثم لا توجد وسيلة لمعرفة أين نهاية الفعلية للملف هو.

إذا كنت تعرف أكثر حول تنسيق البيانات، مثل أن يكون هناك تسلسل بايت فارغة أطول من اثنين بايت (أو بعض قيود مماثلة). فإنك قد تكون قادرة على القيام به في الواقع بحث ثنائي ل 'نقطة التحول ". هذا ينبغي أن يكون أسرع بكثير من البحث الخطي (على افتراض أنه يمكنك قراءة في الملف بأكمله).

والفكرة الأساسية (باستخدام بلدي الافتراض في وقت سابق عن أي بايت اغية التوالي)، ستكون كما يلي:

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