2014-04-25 3 views
0

C#의 HDF5 파일에서 문자열 데이터 세트를 문자열 배열로 읽으려고합니다.HDF5 데이터 세트에서 문자열 배열 읽기

//read the no of rows and columns 
var datasetID = H5D.open(fileId,"dimensions"); 
var dataTypeId = H5D.getType(datasetID); 
var dataType = H5T.getClass(dataTypeId); 
var length = H5T.getSize(dataTypeId); 
int[] dDim = new int[length]; 

H5D.read(datasetID, dataTypeId, new H5Array<int>(dDim)); 

내가 문자열 데이터 세트에 대해 동일한 작업을 수행하려고 노력하지만 모두 null에 초기화 된 값을 얻을 : 나는 다음과 같은 코드를 사용하여 데이터 집합으로 읽을 수 있었다. 그래서이 링크 (https://www.mail-archive.com/[email protected]/msg02980.html)를 참조했습니다. 바이트로 읽을 수 있었지만 바이트 배열을 초기화해야하는 크기를 알지 못합니다. 지금 문자열을 읽는 코드는 다음과 같습니다.

//read string 
datasetID = H5D.open(fileId, "names"); 
var dataSpaceId = H5D.getSpace(datasetID); 
long[] dims = H5S.getSimpleExtentDims(dataSpaceId); 
dataTypeId = H5T.copy(H5T.H5Type.C_S1); 

//hard coding the no of string to read (213) 
byte[] buffer = new byte[dims[0]*213]; 
Console.WriteLine(dims[0]); 
H5D.read(datasetID, dataTypeId, new H5Array<byte>(buffer)); 
Console.WriteLine(System.Text.ASCIIEncoding.ASCII.GetString(buffer)); `. 
+0

문제점이 무엇인지 정확히 이해하지 못합니다. 그것은 효과가 있느냐 없느냐? 그렇지 않은 경우 오류는 무엇입니까? 제발 정교하게 ... – Abbas

+0

나는 데이터 집합에서 문자열의 번호를 찾을 수 없습니다. – gman

+0

그것의 작동하지만 하드 코드 문자열 수 있습니다. 바이트 배열의 크기를 알고 하드 코딩하지 않고 초기화해야하는 방법이 있습니까? – gman

답변

1

데이터 유형을 미리 모르는 경우 다음 코드를 시도하십시오. 데이터 유형은 불완전하지만 쉽게 수정할 수 있습니다.

public static Array Read1DArray(this H5FileId fileId, string dataSetName) 
    { 
     var dataset = H5D.open(fileId, dataSetName); 
     var space = H5D.getSpace(dataset); 
     var dims = H5S.getSimpleExtentDims(space); 
     var dtype = H5D.getType(dataset); 

     var size = H5T.getSize(dtype); 
     var classID = H5T.getClass(dtype); 

     var rank = H5S.getSimpleExtentNDims(space); 
     var status = H5S.getSimpleExtentDims(space); 

     // Read data into byte array 
     var dataArray = new Byte[status[0]*size]; 
     var wrapArray = new H5Array<Byte>(dataArray); 
     H5D.read(dataset, dtype, wrapArray); 

     // Convert types 
     Array returnArray = null; 
     Type dataType = null; 

     switch (classID) 
     { 
      case H5T.H5TClass.STRING: 
       dataType = typeof(string); 
       break; 

      case H5T.H5TClass.FLOAT: 
       if (size == 4) 
        dataType = typeof(float); 
       else if (size == 8) 
        dataType = typeof(double); 
       break; 

      case H5T.H5TClass.INTEGER: 
       if (size == 2) 
        dataType = typeof(Int16); 
       else if (size == 4) 
        dataType = typeof(Int32); 
       else if (size == 8) 
        dataType = typeof(Int64); 
       break; 

     } 

     if (dataType == typeof (string)) 
     { 
      var cSet = H5T.get_cset(dtype); 

      string[] stringArray = new String[status[0]]; 

      for (int i = 0; i < status[0]; i++) 
      { 
       byte[] buffer = new byte[size]; 
       Array.Copy(dataArray, i*size, buffer, 0, size); 

       Encoding enc = null; 
       switch (cSet) 
       { 
        case H5T.CharSet.ASCII: 
         enc = new ASCIIEncoding(); 
         break; 
        case H5T.CharSet.UTF8: 
         enc = new UTF8Encoding(); 
         break; 
        case H5T.CharSet.ERROR: 
         break; 
       } 

       stringArray[i] = enc.GetString(buffer).TrimEnd('\0'); 
      } 

      returnArray = stringArray; 
     } 
     else 
     { 
      returnArray = Array.CreateInstance(dataType, status[0]); 
      Buffer.BlockCopy(dataArray, 0, returnArray, 0, (int) status[0]*size); 
     } 

     H5S.close(space); 
     H5T.close(dtype); 
     H5D.close(dataset); 

     return returnArray; 
    } 
0

시작이 매우 도움이되었습니다! 정확히 같은

//read string 
string[] datasetValue = fileId.Read1DArray<string>("names"); 

가 확장, 또는해야 이런 일을 (보고 : IT 및 HDF5 Example code의 도움으로, 나는에, 그 코드를 줄일 몇 가지 일반적인 확장을 마련 할 수 있었다 참조 된 질문과 같습니다.) :

public static class HdfExtensions 
{ 
    // thank you https://stackoverflow.com/questions/4133377/splitting-a-string-number-every-nth-character-number 
    public static IEnumerable<String> SplitInParts(this String s, Int32 partLength) 
    { 
     if (s == null) 
      throw new ArgumentNullException("s"); 
     if (partLength <= 0) 
      throw new ArgumentException("Part length has to be positive.", "partLength"); 

     for (var i = 0; i < s.Length; i += partLength) 
      yield return s.Substring(i, Math.Min(partLength, s.Length - i)); 
    } 

    public static T[] Read1DArray<T>(this H5FileId fileId, string dataSetName) 
    { 
     var dataset = H5D.open(fileId, dataSetName); 
     var space = H5D.getSpace(dataset); 
     var dims = H5S.getSimpleExtentDims(space); 
     var dataType = H5D.getType(dataset); 
     if (typeof(T) == typeof(string)) 
     { 
      int stringLength = H5T.getSize(dataType); 
      byte[] buffer = new byte[dims[0] * stringLength]; 
      H5D.read(dataset, dataType, new H5Array<byte>(buffer)); 
      string stuff = System.Text.ASCIIEncoding.ASCII.GetString(buffer); 
      return stuff.SplitInParts(stringLength).Select(ss => (T)(object)ss).ToArray(); 
     } 
     T[] dataArray = new T[dims[0]]; 
     var wrapArray = new H5Array<T>(dataArray); 
     H5D.read(dataset, dataType, wrapArray); 
     return dataArray; 
    } 

    public static T[,] Read2DArray<T>(this H5FileId fileId, string dataSetName) 
    { 
     var dataset = H5D.open(fileId, dataSetName); 
     var space = H5D.getSpace(dataset); 
     var dims = H5S.getSimpleExtentDims(space); 
     var dataType = H5D.getType(dataset); 
     if (typeof(T) == typeof(string)) 
     { 
      // this will also need a string hack... 
     } 
     T[,] dataArray = new T[dims[0], dims[1]]; 
     var wrapArray = new H5Array<T>(dataArray); 
     H5D.read(dataset, dataType, wrapArray); 
     return dataArray; 
    } 
} 
관련 문제