2427 {
2428 using (var reader = new BinaryReader(File.Open(filePath, FileMode.Open)))
2429 {
2430
2431 byte[] magic = reader.ReadBytes(6);
2432 string magicString = Encoding.ASCII.GetString(magic);
2433 if (magicString != "?NUMPY")
2434 {
2435 throw new InvalidOperationException("Invalid .npy file.");
2436 }
2437
2438
2439 reader.BaseStream.Seek(2, SeekOrigin.Current);
2440
2441
2442 byte[] headerLengthBytes = reader.ReadBytes(2);
2443 int headerLength = BitConverter.ToInt16(headerLengthBytes, 0);
2444
2445
2446 byte[] headerBytes = reader.ReadBytes(headerLength);
2447 string headerString = Encoding.ASCII.GetString(headerBytes).Replace("True", "true").Replace("False", "false").Replace("(", "[").Replace(")", "]");
2448
2449
2450 var settings = new JsonSerializerSettings
2451 {
2452 ContractResolver = new CamelCasePropertyNamesContractResolver()
2453 };
2454
2455
2456 NpyHeader header = JsonConvert.DeserializeObject<NpyHeader>(headerString, settings);
2457 var shape = header.shape;
2458 var dtype = header.descr;
2459 NpyDataType type = GetNpyTypeEnum(dtype);
2460
2461
2462 int totalElements = shape.Aggregate(1, (acc, dim) => acc * dim);
2463
2464
2466 int dataSize = totalElements * elementSize;
2467
2468
2469 byte[] dataBytes = reader.ReadBytes(dataSize);
2470
2471
2472 Array data = null;
2473 switch (type)
2474 {
2475 case NpyDataType.UInt8:
2476 data = new byte[dataBytes.Length];
2477 Buffer.BlockCopy(dataBytes, 0, data, 0, dataBytes.Length);
2478 break;
2479
2480 case NpyDataType.Int8:
2481 data = new sbyte[dataBytes.Length];
2482 Buffer.BlockCopy(dataBytes, 0, data, 0, dataBytes.Length);
2483 break;
2484
2485 case NpyDataType.UInt16:
2486 data = new ushort[totalElements];
2487 for (int i = 0; i < data.Length; i++)
2488 {
2489 data.SetValue(BitConverter.ToUInt16(dataBytes, i * 2), i);
2490 }
2491 break;
2492
2493 case NpyDataType.Int16:
2494 data = new short[totalElements];
2495 for (int i = 0; i < data.Length; i++)
2496 {
2497 data.SetValue(BitConverter.ToInt16(dataBytes, i * 2), i);
2498 }
2499 break;
2500
2501 case NpyDataType.UInt32:
2502 data = new uint[totalElements];
2503 for (int i = 0; i < data.Length; i++)
2504 {
2505 data.SetValue(BitConverter.ToUInt32(dataBytes, i * 4), i);
2506 }
2507 break;
2508
2509 case NpyDataType.Int32:
2510 data = new int[totalElements];
2511 for (int i = 0; i < data.Length; i++)
2512 {
2513 data.SetValue(BitConverter.ToInt32(dataBytes, i * 4), i);
2514 }
2515 break;
2516
2517 case NpyDataType.UInt64:
2518 data = new ulong[totalElements];
2519 for (int i = 0; i < data.Length; i++)
2520 {
2521 data.SetValue(BitConverter.ToUInt64(dataBytes, i * 8), i);
2522 }
2523 break;
2524
2525 case NpyDataType.Int64:
2526 data = new long[totalElements];
2527 for (int i = 0; i < data.Length; i++)
2528 {
2529 data.SetValue(BitConverter.ToInt64(dataBytes, i * 8), i);
2530 }
2531 break;
2532
2533 case NpyDataType.Float16:
2534
2535
2536 break;
2537
2538 case NpyDataType.Float32:
2539 data = new float[totalElements];
2540 for (int i = 0; i < data.Length; i++)
2541 {
2542 data.SetValue(BitConverter.ToSingle(dataBytes, i * 4), i);
2543 }
2544 break;
2545
2546 case NpyDataType.Float64:
2547 data = new double[totalElements];
2548 for (int i = 0; i < data.Length; i++)
2549 {
2550 data.SetValue(BitConverter.ToDouble(dataBytes, i * 8), i);
2551 }
2552 break;
2553
2554 case NpyDataType.Complex64:
2555 data = new (float, float)[totalElements];
2556 for (int i = 0; i < data.Length; i++)
2557 {
2558 var real = BitConverter.ToSingle(dataBytes, i * 8);
2559 var imaginary = BitConverter.ToSingle(dataBytes, i * 8 + 4);
2560 data.SetValue((real, imaginary), i);
2561 }
2562 break;
2563
2564 case NpyDataType.Complex128:
2565 data = new (double, double)[totalElements];
2566 for (int i = 0; i < data.Length; i++)
2567 {
2568 var real = BitConverter.ToDouble(dataBytes, i * 16);
2569 var imaginary = BitConverter.ToDouble(dataBytes, i * 16 + 8);
2570 data.SetValue((real, imaginary), i);
2571 }
2572 break;
2573
2574 default:
2575 throw new ArgumentException("Unsupported NpyDataType", nameof(type));
2576 }
2577
2578 return (shape, type, data);
2579 }
2580 }
static int GetElementSize(NpyDataType type)
Helper function to get the size of the elements based on dtype.