У меня есть частичное решение ниже; то есть я понял, как читать и декодировать байтовый массив обратно в 2D-массив.
Я сохраняю большой двумерный двойной массив в виде varbinary в SQL.
Я делаю это с помощью Buffer.BlockCopy для создания (линейного) байтового массива из двумерного двойного массива.
У меня для этого определен следующий класс:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestCSSQL
{
class clsMatrixVarbinary
{
Random random = new Random();
public byte[] DoubleMatrixToByteArray(double[,] doubleArray)
{
int rows = doubleArray.GetLength(0);
int cols = doubleArray.GetLength(1);
byte[] byteArray = new byte[rows * cols * sizeof(double)];
Buffer.BlockCopy(doubleArray, 0, byteArray, 0, byteArray.Length);
return byteArray;
}
public double[,] VarBinaryToDoubleMatrix (byte[] byteArray, int rows, int cols)
{
double[,] doubleArray = new double[rows, cols];
for (int r=0; r<rows; r++)
{
for (int c=0; c<cols; c++)
{
doubleArray[r,c] = BitConverter.ToDouble(byteArray, r * cols * sizeof(double) + c * sizeof(double));
}
}
return doubleArray;
}
public double[,] MakeRandomTestMatrix(int rows, int cols)
{
double[,] randomMatrix = new double[rows, cols];
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
randomMatrix[r, c] = random.Next(-200, 200);
}
}
return randomMatrix;
}
// Summation of all cells in a matrix, just a quick verification check.
// The intent is to verify that when a matrix is read from the database,
// the reconstructed matrix has the same checksum as the one that was saved.
//
public double computeChecksum(double[,] dblArray)
{
int rank = dblArray.Rank; // rank is the number of dimensions of an array.
int rows = dblArray.GetLength(0);
int cols = dblArray.GetLength(1);
double sum = 0.0;
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
sum += dblArray[r, c];
}
}
return sum;
}
}
}
Затем я сохраняю некоторую информацию в базе данных SQL - байтовый массив, имя для массива, некоторые примечания, количество строк и столбцов (для восстановления массива) и контрольную сумму ... некоторые другие вещи, не относящиеся к вопрос.
У меня есть процедура тестирования, чтобы убедиться, что C # правильно читает / декодирует и записывает / кодирует.
Но некоторые вещи, которые я хочу сделать с python. У меня есть скрипт, который читает запись из таблицы хранимых матриц (байтовые массивы). Он читает всю информацию правильно (я думаю). Но у меня возникают проблемы с выяснением того, как декодировать сохраненные в varbinary данные (массив байтов в C #).
Я пытаюсь
cursor.execute("SELECT * FROM dbo.test_varbinary_table WHERE [name]= 'CIV' AND [version]= 'AAA'")
result = cursor.fetchone()
rows = result.rows
cols = result.cols
bitString = result.vb_data
Matrix = [[0 for x in range(cols)] for y in range(rows)]
for r in range(rows):
for c in range(cols):
#Original line
#Matrix[r][c] = struct.unpack_from('d', bitString, (r * cols + c)*8)
#This is the fix. Not sure why this is necessary. Need to read docs more thoroughly.
Matrix[r][c] = struct.unpack_from('d', bitString, (r * cols + c)*8)[0]
print(type(Matrix))
sum = 0
for r in range(rows):
for c in range(cols):
sum += Matrix[r][c]
print("sum = " + str(sum))
Однако это не работает, как я ожидаю. Я должен верить, что это обычное дело. Есть ли стандартный способ сделать это?
Изменить: у меня сейчас эта часть работает (или, по крайней мере, кажется). Мне все еще нужно выяснить обратное (создать в Python / сохранить в SQL / прочитать в C # / восстановить двойной массив 2D). Обратите внимание, что единственное, что нужно было получить нулевой элемент кортежа.
И вот, это правильно в документе, который я прочитал 3 раза:
"struct.unpack_from (fmt, buffer, offset = 0)
... В результате получается кортеж, даже если он содержит ровно один элемент ... "
https://docs.python.org/3.1/library/struct.html#struct-alignment