2016-09-27 1 views
-1

Je suis en train de faire une routine de manipulation pour encoder/décoder des fichiers mp3. Cependant, je devrai les encoder en utilisant C#, et les décoder en utilisant Delphi XE 10. J'ai écrit le code qui les code/les décode, et ça marche quand il est exécuté sur la même plate-forme (si je code/décode en C# , et si je code/décode en Delphi les jeux mp3), mais si j'essaye de décoder un mp3 encodé en C#, le mp3 ne joue pas. En faisant ce processus seulement avec la chaîne, cela a fonctionné, donc c'est probablement quand j'ai essayé de l'appliquer au MemoryStream. À la fin, j'ai édité le poste, et ajouté les fonctions que j'ai utilisé les chaînes encoder/décoder seulement, et je peux encoder avec succès en C#, et décoder en Delphi. J'ai changé la chaîne de hachage, mais il est similaire à celui utilisé dans les échantillonsCompatibilité sur la manipulation de bits entre C# et Delphi lors de la gestion de fichiers

Voici le code en C#:

private void btnCodificarArquivos_Click(object sender, EventArgs e) 
{ 
    Encoding ANSI = Encoding.GetEncoding(1252); 
    byte[] hash = ANSI.GetBytes(@"laki#~~2p3fijo3ij881*2f-|- a`asso`wpeofi#[email protected]"); 
    string directory; 
    string originalExtension; 
    string finalExtension; 
    if (cbxCodificar.Checked) 
    { 
      originalExtension = "mp3"; 
      finalExtension = "mpc"; 
    } 
    else 
    { 
      originalExtension = "mpc"; 
      finalExtension = "mp3"; 
    } 
    directory = txbFrase.Text.Trim(); 
    if (!Directory.Exists(directory)) 
      throw new Exception("Directory does not exist => " + directory); 
    var files = Directory.GetFiles(directory, "*." + originalExtension); 
    foreach (var file in files) 
    { 
     using (FileStream streamFile = new FileStream(file, FileMode.Open, FileAccess.ReadWrite)) 
     { 
      using (MemoryStream codedMemory = new MemoryStream()) 
      { 
       streamFile.CopyTo(codedMemory); 
       byte[] fileArray = codedMemory.ToArray(); 

       byte[] output = new byte[fileArray.Length]; 
       for (int i = 0; i < fileArray.Length; i++) 
        output[i] = (byte)(fileArray[i]^~hash[(i + 1) % hash.Length]); 
       using (MemoryStream memoryCodificado = new MemoryStream(output)) 
       { 
        string fileDestination = Path.ChangeExtension(file, "." + finalExtension); 
        if (File.Exists(fileDestination)) 
         File.Delete(fileDestination); 
        using (FileStream arquivoFinal = new FileStream(fileDestination, FileMode.Create, FileAccess.ReadWrite)) 
        { 
         memoryCodificado.Position = 0; 
         memoryCodificado.CopyTo(arquivoFinal); 
        } 
       } 
      } 
     } 
    } 
} 

}

est Ci-dessous le code Delphi:

procedure TfrmEncodeDecode.btnCodificarArquivoClick(Sender: TObject); 
const 
    Hash: string = 'laki#~~2p3fijo3ij881*2f-|- a`asso`wpeofi#[email protected]'; 
var 
    counter, i: Integer; 
    bufferStream : ^Byte; 
    streamSize: Int64; 
    streamFile: TFileStream; 
    listFiles: TStringDynArray; 
    codedMemory: TMemoryStream; 
    directory, originalExtension, finalExtension, fileDestination: string; 
begin 
    if (cbxConverter.Checked) then 
    begin 
    originalExtension := 'mp3'; 
    finalExtension := 'mpc'; 
    end 
    else 
    begin 
    originalExtension := 'mpc'; 
    finalExtension := 'mp3'; 
    end; 
    directory := String(edtFrase.Text).Trim; 
    if (not TDirectory.Exists(directory, true)) then 
    raise Exception.Create('Diretório não existe => ' + directory); 
    listFiles := TDirectory.GetFiles(directory, '*.' + originalExtension); 
    if (Length(listFiles) > 0) then 
    begin 
    for counter := 0 to Pred(Length(listFiles)) do 
    begin 
     streamFile := TFileStream.Create(listFiles[counter], fmOpenRead, fmShareExclusive); 
     try 
     codedMemory := TMemoryStream.Create; 
     try 
      codedMemory.CopyFrom(streamFile, streamFile.Size); 
      fileDestination := TPath.ChangeExtension(listFiles[counter], '.' + finalExtension); 
      if (TFile.Exists(fileDestination, true)) then 
      TFile.Delete(fileDestination); 
      streamSize := codedMemory.Size; 
      bufferStream := codedMemory.Memory; 
      i := 0; 
      while (i < streamSize) do 
      begin 
      bufferStream^ := Byte(ord (bufferStream^) xor not (Ord (Hash[I mod Length (Hash) + 1]))); 
      Inc(bufferStream); 
      Inc(i); 
      end; 
      codedMemory.SaveToFile(fileDestination); 
     finally 
      codedMemory.Free; 
     end; 
     finally 
     streamFile.Free; 
     end; 
    end; 
    end; 
end; 

EDIT

compléme En réponse à la question, vous trouverez ci-dessous le code de la chaîne encoder/décoder. Faire cela pour la chaîne, je peux coder en C# et le décoder Delphi sans problème:

private string EncodeDecode(string str) 
{ 
    Encoding ANSI = Encoding.GetEncoding(1252); 
    byte[] hash = ANSI.GetBytes(@"laki#~~2p3fijo3ij881*2f-|- a`asso`wpeofi#[email protected]"); 
    byte[] input = ANSI.GetBytes(str); 
    byte[] output = new byte[input.Length]; 
    for (int i = 0; i < input.Length; i++) 
     output[i] = (byte)(input[i]^~hash[(i + 1) % hash.Length]); 
    return ANSI.GetString(output); 
} 

et ci-dessous est le code Delphi

function TfrmEncodeDecode.EncodeDecode(palavra: AnsiString): AnsiString; 
const 
    Hash: string = 'laki#~~2p3fijo3ij881*2f-|- a`asso`wpeofi#[email protected]'; 
var 
    I: Integer; 
begin 
    Result := palavra; 
    for I := 1 to Length (Result) do 
    Result[I] := AnsiChar (ord (Result[I]) xor not (Ord (Hash[I mod Length (Hash) + 1]))); 
end; 

EDIT

Après Ken` s commente, j'ai changé le côté Delphi pour que le hash soit converti en un tableau d'octets, comme le montre le code ci-dessous, et maintenant le mp3 joue effectivement lorsqu'il est encodé en C# et décodé en Delphi, mais la chanson ressemble à un disque rayé quand ça joue. Ci-dessous le nouveau code Delphi:

procedure TfrmEncodeDecode.btnCodificarArquivoClick(Sender: TObject); 
const 
    Hash: string = 'laki#~~2p3fijo3ij881*2f-|- a`asso`wpeofi#[email protected]'; 
var 
    counter, i: Integer; 
    bufferStream : ^Byte; 
    streamSize: Int64; 
    aHash: TArray<Byte>; 
    streamFile: TFileStream; 
    listFiles: TStringDynArray; 
    codedMemory: TMemoryStream; 
    directory, originalExtension, finalExtension, fileDestination: string; 
begin 
    aHash := TEncoding.ANSI.GetBytes(Hash); 
    if (cbxConverter.Checked) then 
    begin 
    originalExtension := 'mp3'; 
    finalExtension := 'mpc'; 
    end 
    else 
    begin 
    originalExtension := 'mpc'; 
    finalExtension := 'mp3'; 
    end; 
    directory := String(edtFrase.Text).Trim; 
    if (not TDirectory.Exists(directory, true)) then 
    raise Exception.Create('Diretório não existe => ' + directory); 
    listFiles := TDirectory.GetFiles(directory, '*.' + originalExtension); 
    if (Length(listFiles) > 0) then 
    begin 
    for counter := 0 to Pred(Length(listFiles)) do 
    begin 
     streamFile := TFileStream.Create(listFiles[counter], fmOpenRead, fmShareExclusive); 
     try 
     codedMemory := TMemoryStream.Create; 
     try 
      codedMemory.CopyFrom(streamFile, streamFile.Size); 
      fileDestination := TPath.ChangeExtension(listFiles[counter], '.' + finalExtension); 
      if (TFile.Exists(fileDestination, true)) then 
      TFile.Delete(fileDestination); 
      streamSize := codedMemory.Size; 
      bufferStream := codedMemory.Memory; 
      i := 0; 
      while (i < streamSize) do 
      begin 
      bufferStream^ := Byte(ord (bufferStream^) xor not (Ord (aHash[I mod Length (aHash) + 1]))); 
      Inc(bufferStream); 
      Inc(i); 
      end; 
      codedMemory.SaveToFile(fileDestination); 
     finally 
      codedMemory.Free; 
     end; 
     finally 
     streamFile.Free; 
     end; 
    end; 
    end; 
end; 

J'ai vérifié chacun des 62 octets dans le tableau, on compare les valeurs de C# avec les valeurs Delphi, et ils correspondent parfaitement, il est donc pas un problème de codage lors de la conversion la chaîne au tableau Byte

+2

* il ne fonctionne pas * est une description du problème tout à fait dénué de sens. Comment ** spécifiquement ** ça * ne marche pas *? Vous devez [modifier] votre question et indiquer clairement le problème que vous rencontrez avec les blocs de code que vous avez publiés. Vous n'avez encore rien expliqué. –

+0

Lorsque j'essaie de lire le mp3 encodé en C# après décodage en Delphi, il ne joue pas. Il woks avec des chaînes simples, mais maintenant avec des fichiers. Si je code/décode en Delphi, le mp3 joue. Si je code/décode en C#, le mp3 joue – Pascal

+1

Comme je l'ai dit, [edit] votre question et ** expliquez clairement le problème ** dans la question elle-même. L'enterrer dans les commentaires n'est pas plus utile que de dire que ça ne marche pas *. –

Répondre

1

Avec l'aide précieuse de Ken, Tom et David dans les commentaires, j'ai été capable de le déboguer et de trouver la cause première du code. Ci-dessous le code C# et Delphi pour tous ceux qui ont besoin de ce type d'informations de gestion de bit sur MemoryStream.

private void btnCodificarArquivos_Click(object sender, EventArgs e) 
    { 
     Encoding ANSI = Encoding.GetEncoding(1252); 
     byte[] hash = ANSI.GetBytes(@"laki#~~2p3fijo3ij881*2f-|- a`asso`wpeofi#[email protected]"); 
     string directory; 
     string originalExtension; 
     string finalExtension; 
     string debugFileName; 
     TextWriter debugFile = null; 
     if (cbxCodificar.Checked) 
     { 
      originalExtension = "mp3"; 
      finalExtension = "mpc"; 
     } 
     else 
     { 
      originalExtension = "mpc"; 
      finalExtension = "mp3"; 
     } 
     directory = txbFrase.Text.Trim(); 
     if (!Directory.Exists(directory)) 
      throw new Exception("Directory does not exist => " + directory); 
     var files = Directory.GetFiles(directory, "*." + originalExtension); 
     foreach (var file in files) 
     { 
      using (FileStream streamFile = new FileStream(file, FileMode.Open, FileAccess.ReadWrite)) 
      { 
       using (MemoryStream codedMemory = new MemoryStream()) 
       { 
        debugFileName = Path.ChangeExtension(file, ".txt"); 
        if (cbxDebugar.Checked) 
        { 
         debugFile = new StreamWriter(debugFileName); 
        } 
        streamFile.CopyTo(codedMemory); 
        byte[] fileArray = codedMemory.ToArray(); 

        byte[] output = new byte[fileArray.Length]; 
        for (int i = 0; i < fileArray.Length; i++) 
        { 
         output[i] = (byte)(fileArray[i]^~hash[(i + 1) % hash.Length]); 
         if (cbxDebugar.Checked) 
          debugFile.WriteLine(output[i]); 
        } 
        using (MemoryStream memoryCodificado = new MemoryStream(output)) 
        { 
         string fileDestination = Path.ChangeExtension(file, "." + finalExtension); 
         if (File.Exists(fileDestination)) 
          File.Delete(fileDestination); 
         using (FileStream arquivoFinal = new FileStream(fileDestination, FileMode.Create, FileAccess.ReadWrite)) 
         { 
          memoryCodificado.Position = 0; 
          memoryCodificado.CopyTo(arquivoFinal); 
         } 
        } 
        if (cbxDebugar.Checked) 
        { 
         debugFile.Flush(); 
         debugFile.Close(); 
         debugFile = null; 
        } 
       } 
      } 
     } 
    } 

ici est le code de Delphi:

procedure TfrmEncodeDecode.btnCodificarArquivoClick(Sender: TObject); 
const 
    Hash: string = 'laki#~~2p3fijo3ij881*2f-|- a`asso`wpeofi#[email protected]'; 
var 
    counter, i: Integer; 
    bufferStream : ^Byte; 
    streamSize: Int64; 
    aHash: TArray<Byte>; 
    debugFile: TextFile; 
    streamFile: TFileStream; 
    listFiles: TStringDynArray; 
    codedMemory: TMemoryStream; 
    directory, originalExtension, finalExtension, fileDestination, debugFileName: string; 
begin 
    aHash := TEncoding.ANSI.GetBytes(Hash); 
    if (cbxConverter.Checked) then 
    begin 
    originalExtension := 'mp3'; 
    finalExtension := 'mpc'; 
    end 
    else 
    begin 
    originalExtension := 'mpc'; 
    finalExtension := 'mp3'; 
    end; 
    directory := String(edtFrase.Text).Trim; 
    if (not TDirectory.Exists(directory, true)) then 
    raise Exception.Create('Diretório não existe => ' + directory); 
    listFiles := TDirectory.GetFiles(directory, '*.' + originalExtension); 
    if (Length(listFiles) > 0) then 
    begin 
    for counter := 0 to Pred(Length(listFiles)) do 
    begin 
     streamFile := TFileStream.Create(listFiles[counter], fmOpenRead, fmShareExclusive); 
     try 
     codedMemory := TMemoryStream.Create; 
     try 
      codedMemory.CopyFrom(streamFile, streamFile.Size); 
      fileDestination := TPath.ChangeExtension(listFiles[counter], '.' + finalExtension); 
      if (TFile.Exists(fileDestination, true)) then 
      TFile.Delete(fileDestination); 
      debugFileName := TPath.ChangeExtension(listFiles[counter], '.txt'); 
      if (TFile.Exists(debugFileName, true)) then 
      TFile.Delete(debugFileName); 
      streamSize := codedMemory.Size; 
      bufferStream := codedMemory.Memory; 
      i := 0; 
      if (cbxDebugar.Checked) then 
      begin 
      AssignFile(debugFile, debugFileName); 
      ReWrite(debugFile); 
      end; 
      try 
      while (i < streamSize) do 
      begin 
       bufferStream^ := Byte(ord (bufferStream^) xor not (Ord (aHash[(I+1) mod Length (aHash)]))); 
       if (cbxDebugar.Checked) then 
       Writeln(debugFile, bufferStream^); 
       Inc(bufferStream); 
       Inc(i); 
      end; 
      finally 
      if (cbxDebugar.Checked) then 
      begin 
       Flush(debugFile); 
       CloseFile(debugFile); 
      end; 
      end; 
      codedMemory.SaveToFile(fileDestination); 
     finally 
      codedMemory.Free; 
     end; 
     finally 
     streamFile.Free; 
     end; 
    end; 
    end; 
end;