none
Como puedo usar el metodo insertar, remover y remplazar en un archivo binario? en C# RRS feed

  • Pregunta

  • Bueno como dice el titulo necesito ayuda sobre esos metodos que se usan en el substring el problema es que no se pueden utilizar perfectamente en un archivo binario como se usaria en un archivo texto ya que los archivos binarios llevan 256 caracteres y los archivos de texto solo llevan 127 caracteres creo, por esa razon no puedo escribir una secuencia de byte como debe ser lo que mas necesito y es por eso esta pregunta es como usar los metodos insert, remove y replace en un archivo binario o si hay algun metodo parecido a los metodos del substring para usar con caracteres especiales que tienen los hexadecimales

    En esta pagina explica como usar esos metodos en un string pero necesito saber como aplicarlos en un byte array ya que si lo hago con un string y lo paso al byte array y lo escribo en un archivo binario los caracteres especiales se convierten en un signo de interrogacion "?"

    Pagina:

    https://www.codigomaestro.com/programacion-c-vb-java/reemplazar-un-string-por-posicion/

    Espero que me puedan ayudar con esto por favor y desde ya muchas gracias

    sábado, 18 de enero de 2020 5:39

Respuestas

  • No, efectivamente no puedes convertir el archivo binario en un string para insertar y borrar porciones, porque no existe una correspondencia unívoca entre todas las posibles combinaciones de bytes y la codificación de los strings, que usan Unicode. Esto hace que con un archivo binario que contenga bytes arbitrarios se pierda información al convertirlo de ida y de vuelta en un string.

    Por cierto, no es exacto que los binarios tengan 256 valores por byte (me imagino que eso es lo que querías decir cuando escribiste "256 caracteres") y los de texto 127. En realidad los de texto se pueden crear con distintos tipos de codificación tales como UTF-8, que permite almacenar cientos de miles de caracteres distintos, y esto lo hace mapeando cada uno de los caracteres superiores al 127 en dos o más bytes, usando el primero como código que indica que detrás vienen varios que se deben considerar juntos. Desde luego, hay muchas secuencias que no tienen sentido y por eso no puedes convertir en string un archivo que contienen bytes arbitrarios.

    Entonces, ¿Cómo se inserta y borra en un archivo binario? Pues se lee hacia un array de bytes. Si el archivo no es muy grande, puedes leerlo todo de golpe con la instrucción File.ReadAllBytes. Y después, como los arrays en .Net no pueden cambiar de tamaño, lo que haces es que asignas en memoria otro nuevo array que tenga la longitud final deseada (réstale al original el número de bytes que quieras borrar, y súmale los que quieras añadir). Entonces usas bucles para copiar del array original al array nuevo las partes que quieras conservar en la posición en la que deban quedar. Puedes auxiliarte si lo deseas de la instrucción Array.Copy, que permite copiar un rango de bytes de un array. Cuando termines, usas File.WriteAllBytes para escribir el nuevo array en el archivo de destino.

    sábado, 18 de enero de 2020 9:07
    Moderador
  • Bien, eso mismo que haces con Strings no se puede hacer con bytes. O mejor dicho, no es que no se pueda hacer, lo que pasa es que no existe una función ya hecha que te lo dé resuelto. Tendrías que escribirla tú mismo, copiando bytes de un sitio a otro.

    Por ejemplo "que pueda agregar entremedio de dos bytes una secuencia de bytes sin tocar los bytes que estan alrededor". Pues no, no se puede hacer sin tocar los bytes que están alrededor. Hay que tocarlos absolutamente todos. Por ejemplo, supongamos que partes de este array de bytes:

    byte[] b1 = new byte[] { 0,1,2,3,4,5,6,7,8,9 };

    y supongamos que entre las posiciones 4 y 5 quieres insertar los valores { 10,11,12 }. Pues bien, no los puedes insertar en el mismo array, porque la longitud resultante es distinta y los arrays no pueden cambiar de tamaño una vez asignados. Así que tienes que construir otro nuevo array con la longitud requerida, que en este caso serían 13 bytes:

    byte[] b2 = new byte[13];

    Entonces copias desde b1 a b2 los bytes 0 a 4. Después metes { 10,11,12 } en las posiciones 5 a 7 de b2. Y finalmente, copias lo que hay en las posiciones 5 a 9 de b1 a las posiciones 8 a 12 de b2.

    Como ves, hay que tocar todos los bytes (nos ha hecho falta tocarlos todos para asar de b1 a b2) además de insertar en el sitio adecuado los bytes que queríamos insertar.

    Como ves, es más complicado que con los strings, porque no hay un "InsertAt" que nos lo resuelva directamente. Maticemos esto: no lo hay si quieres usar un array. Podrías cargar todo el archivo en un List<byte> y entonces sí que existe InsertAt y RemoveAt para hacer modificaciones. Pero si el fichero es grande, el List<byte> será muchísimo más lento que el array de bytes.

    sábado, 18 de enero de 2020 16:15
    Moderador
  • Muchas gracias amigo a funcionado con el List<byte> y los metodos InsertRange y RemoveRange, lo que hice es cargar todo el archivo en un array y luego una parte de otro archivo en otro array y luego esto es una opcion borre los bytes que necesitaba borrar con RemoveRange(offset, length) y los elimina, despues use InsertRange(offset, byte[] array) y los inserta entremedio del offset elejido y la cantidad de bytes a  copiar sin tocar ningun byte que este alrededor.

    Muchas gracias amigo me ha servido mucho hablar contigo me asesoraste muy bien sobre lo que necesitaba

    lunes, 20 de enero de 2020 4:50

Todas las respuestas

  • No, efectivamente no puedes convertir el archivo binario en un string para insertar y borrar porciones, porque no existe una correspondencia unívoca entre todas las posibles combinaciones de bytes y la codificación de los strings, que usan Unicode. Esto hace que con un archivo binario que contenga bytes arbitrarios se pierda información al convertirlo de ida y de vuelta en un string.

    Por cierto, no es exacto que los binarios tengan 256 valores por byte (me imagino que eso es lo que querías decir cuando escribiste "256 caracteres") y los de texto 127. En realidad los de texto se pueden crear con distintos tipos de codificación tales como UTF-8, que permite almacenar cientos de miles de caracteres distintos, y esto lo hace mapeando cada uno de los caracteres superiores al 127 en dos o más bytes, usando el primero como código que indica que detrás vienen varios que se deben considerar juntos. Desde luego, hay muchas secuencias que no tienen sentido y por eso no puedes convertir en string un archivo que contienen bytes arbitrarios.

    Entonces, ¿Cómo se inserta y borra en un archivo binario? Pues se lee hacia un array de bytes. Si el archivo no es muy grande, puedes leerlo todo de golpe con la instrucción File.ReadAllBytes. Y después, como los arrays en .Net no pueden cambiar de tamaño, lo que haces es que asignas en memoria otro nuevo array que tenga la longitud final deseada (réstale al original el número de bytes que quieras borrar, y súmale los que quieras añadir). Entonces usas bucles para copiar del array original al array nuevo las partes que quieras conservar en la posición en la que deban quedar. Puedes auxiliarte si lo deseas de la instrucción Array.Copy, que permite copiar un rango de bytes de un array. Cuando termines, usas File.WriteAllBytes para escribir el nuevo array en el archivo de destino.

    sábado, 18 de enero de 2020 9:07
    Moderador
  • Gracias por tu respuesta lo mismo que dijiste eso me pasa cuando convierto de string a byte array no me deja copiar los caracteres especiales asi que intentare ver si me funciona con lo que explicaste, esto que decis funciona para agregar bytes en un determinado offset y la cantidad de bytes que quiero entremedio como lo hace el metodo insert desde un punto al otro sin tocar los demas datos

    Por que quiero que haga lo mismo que esto pero en byte, de que pueda agregar entremedio de dos bytes una secuencia de bytes sin tocar los bytes que estan alrededor espero que me haya explicado bien y para remover lo mismo que pueda fijar como si tuviera usando un seek de un principio hasta el offset que quiera y luego borrar. Se leer y escrbir secuencias de bytes pero me falta esa ayudita de que quiero remover o agregar entremedio de un punto al otro sin tocar los demas datos es algo que me serviria demasiado ya que a veces necesito colocar una secuencia de byte mayor o menor a la de el otro archivo de un offset a otro offset como en este ejemplo de abajo

    diferentes formas de reemplazar una cadena del tipo de datos string en determinada posición. Lo vamos a ver tanto para el lenguaje de programación C# como para VB.

    Supongamos que tenemos el string: ABCDEFGHIJK y necesitamos reemplazar desde la posición 4 a la 5  de esa cadena por “YZ“, y como resultado deseamos que quede: ABCYZFGHIJK

    ¿Cómo lo podemos hacer?

    1. Existen varias maneras de poder hacerlo, la manera sencilla de agregar o quitar rangos es utilizar la clase StringBuilder.
    C#
    var elString = "ABCDEFGHIJK";
    var aStringBuilder = new StringBuilder(elString);
    aStringBuilder.Remove(3, 2);
    aStringBuilder.Insert(3, "YZ");
    elString = aStringBuilder.ToString();


    3. Otra forma de hacer esta tarea es usando una extensión del método que no usa StringBuilder ni tampoco SubString, esta forma es muy buena porque permite ampliar el tamaño del String sin ningún problema.

    ReplaceAt(int index, int longitud, string reemplazo)

    C#
    //// cadena - la cadena string original
    //// index- la ubicación inicial a ser reemplazada(0-base)
    //// length - el número de caracteres a ser removido antes de la inserción
    //// replace - la cadena que reemplazará
    public static string ReplaceAt(this string cadena, int index, int length, string replace)
    {
        return cadena.Remove(index, Math.Min(length, cadena.Length - index)).Insert(index, replace);
    }

    Algunos ejemplos de RelaceAt:

    "0123456789".ReplaceAt(7, 5, "Hola") = "0123456Hola"

    Si se específica una longitud de 0, está función retornará simplemente una inserción:

    "0123456789".ReplaceAt(4, 0, "Hola") = "0123Hola456789"

     

    Existen varias formas más de hacer lo mismo, pero creo que con estás formas ya se pueden imaginar las restantes.

    sábado, 18 de enero de 2020 14:08
  • Bien, eso mismo que haces con Strings no se puede hacer con bytes. O mejor dicho, no es que no se pueda hacer, lo que pasa es que no existe una función ya hecha que te lo dé resuelto. Tendrías que escribirla tú mismo, copiando bytes de un sitio a otro.

    Por ejemplo "que pueda agregar entremedio de dos bytes una secuencia de bytes sin tocar los bytes que estan alrededor". Pues no, no se puede hacer sin tocar los bytes que están alrededor. Hay que tocarlos absolutamente todos. Por ejemplo, supongamos que partes de este array de bytes:

    byte[] b1 = new byte[] { 0,1,2,3,4,5,6,7,8,9 };

    y supongamos que entre las posiciones 4 y 5 quieres insertar los valores { 10,11,12 }. Pues bien, no los puedes insertar en el mismo array, porque la longitud resultante es distinta y los arrays no pueden cambiar de tamaño una vez asignados. Así que tienes que construir otro nuevo array con la longitud requerida, que en este caso serían 13 bytes:

    byte[] b2 = new byte[13];

    Entonces copias desde b1 a b2 los bytes 0 a 4. Después metes { 10,11,12 } en las posiciones 5 a 7 de b2. Y finalmente, copias lo que hay en las posiciones 5 a 9 de b1 a las posiciones 8 a 12 de b2.

    Como ves, hay que tocar todos los bytes (nos ha hecho falta tocarlos todos para asar de b1 a b2) además de insertar en el sitio adecuado los bytes que queríamos insertar.

    Como ves, es más complicado que con los strings, porque no hay un "InsertAt" que nos lo resuelva directamente. Maticemos esto: no lo hay si quieres usar un array. Podrías cargar todo el archivo en un List<byte> y entonces sí que existe InsertAt y RemoveAt para hacer modificaciones. Pero si el fichero es grande, el List<byte> será muchísimo más lento que el array de bytes.

    sábado, 18 de enero de 2020 16:15
    Moderador
  • Los archivos que trabajo no pesan mas de 2mb.

    Entonces es posible hacer eso con List<byte> usando insertAt y RemoveAt, si no funciona con ese tamaño de archivo probare con lo me dijiste a ver si puedo hacer algo, algunos programas que vi hacen lo que digo yo de copiar una secuencia de bytes entremedio de algunos bytes en C# alguna manera hay pero soy casi novato en esto y se me complica demasiado en esa parte porque lo demas lo se de leer un archivo y ponerlo en un array de byte y escribirlo en el archivo pero me faltaba eso

    sábado, 18 de enero de 2020 17:52
  • Muchas gracias amigo a funcionado con el List<byte> y los metodos InsertRange y RemoveRange, lo que hice es cargar todo el archivo en un array y luego una parte de otro archivo en otro array y luego esto es una opcion borre los bytes que necesitaba borrar con RemoveRange(offset, length) y los elimina, despues use InsertRange(offset, byte[] array) y los inserta entremedio del offset elejido y la cantidad de bytes a  copiar sin tocar ningun byte que este alrededor.

    Muchas gracias amigo me ha servido mucho hablar contigo me asesoraste muy bien sobre lo que necesitaba

    lunes, 20 de enero de 2020 4:50