私はC#にかなり慣れていないので、これを許してください。私はこれで長い間頭を壁にぶつけていましたが、解決策が見つかりません. おそらくそれは非常に明白なことです。
オブジェクトのプロパティをファイルに書き込んでいます。最初にプロパティをバイト配列に変換し、次に配列全体 (「1 つのオブジェクト」) をまとめて、Aes を使用して MemoryStream 経由で暗号化します。シリアル化やその他の可能性については知っていますが、本当にこの方法で行う必要があります。他の方法では、このファイルをチャンク (「オブジェクト」) で読み取り、復号化し、バイト配列からオブジェクト プロパティを再構築します。問題は、最初のレコード (「オブジェクト」) のみが復号化され、正常に/正しく再構築されることです。他のすべてのデータはめちゃくちゃになります (int は 2 ではなく 48464 の値を取得し、文字列は奇数の符号を示し、double は 20 ではなく -3.16...E-161 になります...)。
そして、私には理由がわかりません。考えられる限りのことはすべて試しました。暗号化と復号化をコメントアウトするとすべてが機能するので、書き込みと読み取りには問題ありません。オブジェクトの復号化と再構築のコードを暗号化のコードのすぐ下に配置すると (書き込まれたデータ チャンクを復号化するため)、すべてが適切に復号化および再構築されるため、復号化と再構築の問題にはなりません。しかし、それがすべて一緒になると、それはめちゃくちゃになります。私はここで本当に迷っています。
私がデータを操作する方法に集中しないでください。今はそれほど重要ではありません。なぜこのようにするのかには理由があります。
ファイルに保存するためのコード全体を次に示します。
//constant for setting inUse
byte setInUse = 0x80; //1000 0000
//constant for adding spaces to name (string)
byte[] space = Encoding.UTF8.GetBytes(" ");
//result
byte[] data = new byte[32];
//setup encryption (AES)
SymmetricAlgorithm aes = Aes.Create();
byte[] key = { 145, 12, 32, 245, 98, 132, 98, 214, 6, 77, 131, 44, 221, 3, 9, 50 };
byte[] iv = { 15, 122, 132, 5, 93, 198, 44, 31, 9, 39, 241, 49, 250, 188, 80, 7 };
aes.Padding = PaddingMode.None;
ICryptoTransform encryptor = aes.CreateEncryptor(key, iv);
//setup file stream for saving data
FileStream fStream = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read, 1024, false);
if(writeIndex != 0)
fStream.Position = writeIndex +1;
fStream.Position = 0; //delete me
foreach(Article article in articles)
{
if(article.MyIsNew)
{
article.MyInUseChanged = false;
article.MyPriceChanged = false;
//convert article to byte array
//id
byte[] id = BitConverter.GetBytes(Convert.ToUInt16(article.MyId));
//in use
if (article.MyInUse)
id[0] = (byte)( id[0] | setInUse);
data[0] = id[0];
data[1] = id[1];
//stock
byte[] stock = BitConverter.GetBytes(article.MyStock);
data[2] = stock[0];
data[3] = stock[1];
data[4] = stock[2];
data[5] = stock[3];
data[6] = stock[4];
data[7] = stock[5];
data[8] = stock[6];
data[9] = stock[7];
//name
byte[] name = Encoding.UTF8.GetBytes(article.MyName);
int counter = 10;
for (int i = 0; i < name.Length; i++)
{
data[counter] = name[i];
counter++;
}
//adding spaces
int numToAdd = 22-name.Length;
for (int i = 0; i < numToAdd; i++)
{
data[counter] = space[0];
}
//encrypt
MemoryStream m = new MemoryStream();
using (Stream c = new CryptoStream(m, encryptor, CryptoStreamMode.Write))
c.Write(data, 0, data.Length);
byte[] original = new byte[32];
original = m.ToArray();
fStream.Write(original, 0, original.Length);
}
else if (article.MyInUseChanged)
{
}
if (article.MyPriceChanged)
{
}
}
fStream.Flush();
fStream.Close();
fStream.Dispose();
そして、ロードするためのコード全体は次のとおりです。
String fileName = path + "\\articles";
//load data
if (File.Exists(fileName))
{
FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false);
//setup encryption (AES)
SymmetricAlgorithm aes = Aes.Create();
byte[] key = { 145, 12, 32, 245, 98, 132, 98, 214, 6, 77, 131, 44, 221, 3, 9, 50 };
byte[] iv = { 15, 122, 132, 5, 93, 198, 44, 31, 9, 39, 241, 49, 250, 188, 80, 7 };
aes.Padding = PaddingMode.None;
ICryptoTransform decryptor = aes.CreateDecryptor(key, iv);
//constant for extracting inUse
byte inUseConst = 0x80;
//constant for extracting id
byte idConst = 0x7F;
byte[] idArray = new byte[2];
//reading & constructing & adding articles to the list
int numBytesToRead = (int)fStream.Length;
while (numBytesToRead > 0)
{
byte[] original = new byte[32];
byte[] data = new byte[32];
int len = fStream.Read(original, 0, 32);
numBytesToRead -= 32;
if (len == 0 || len != 32)
{
MessageBox.Show("Error while loading articles");
break;
}
long pos = fStream.Position; //delete me
//decrypt
MemoryStream m = new MemoryStream();
using (Stream c = new CryptoStream(m, decryptor, CryptoStreamMode.Write))
c.Write(original, 0, original.Length);
data = m.ToArray();
//constructing object - article
//inUse
byte inUseCalc = (byte)(data[0] & inUseConst);
bool inUse = false;
if (inUseCalc != 0)
{
inUse = true;
}
//id
data[0] = (byte)(data[0] & idConst);
int id = (int)(BitConverter.ToUInt16(data, 0));
//stock
double stock = BitConverter.ToDouble(data, 2);
//name
String name = Encoding.UTF8.GetString(data, 10, 22);
Article article = new Article(id, 10, name, inUse, stock);
articles.Add(article);
解決策を見つけるためだけに多くの変更を加えたため、最適でないものもあります。いくつかのこと (uInt16 への変換や「or」などの使用など) は部分的に圧縮が原因です。
これを解決するのを手伝ってください。また、データの取り扱いに集中したり、シリアライゼーションやバイナリライターなどを使用するようにアドバイスしたりしないでください。本当に理由があります。
私は完全にアイデアがないので、本当にあなたを頼りにしています。皆様、貴重なお時間とご回答ありがとうございます。