C#读取横河WVF数据文件

横河wvf型数据,分别保存在hdr(数据信息文件)和wvf(数据文件)两个文件中。

其中HDR文件格式及参数可以参考: http://www.yokogawa.com/jp-ymi/tm/TI/TIdoc/TI700021.pdf

1.保存hdr中数据信息的结构体

View Code
//.hdr文件的wvf文件信息struct
public struct WVFInfo
{
    public string FileName;
    public string FormatVersion;
    public string Model;
    public WVFEndianType Endian;
    public string DataFormat;
    public int GroupNumber;
    public int TraceTotalNumber;
    public int DataOffset;
    public List<WVFGroup> Groups;
}

//wvf group struct
public struct WVFGroup
{
    public int TraceNumber;
    public int BlockNumber;

    //Traces
    public List<string> TraceName;
    public List<int> BlockSize;
    public List<double> VResolution;
    public List<double> VOffset;
    public List<WVFByteFormatType> VDataTypeByteFormat;
    public List<int> VDataTypeByteNumber;
    public List<string> VUnit;
    public List<string> VPlusOverData;
    public List<string> VMinusOverData;
    public List<double> VIllegalData;
    public List<double> VMaxData;
    public List<double> VMinData;
    public List<double> HResolution;
    public List<double> HOffset;
    public List<string> HUnit;

    //currently only support 1 block
    public List<string> Date;
    public List<string> Time;
    public List<List<double>> TValues;
    public List<List<double>> YValues;
}

//wvf文件的数据格式struct
public enum WVFByteFormatType
{
    IS = 0, //int
    IU = 1, //unsigned int
    FS = 2, //float
}

//wvf文件的数据大小端struct
public enum WVFEndianType
{
    Big = 0, //Big Endian
    Little = 1 //Little Endian
}

2.读取hdr时会用到的字符串操作函数

View Code
string fileparse(string keyword, string text)
{
    string value = "";
    int indexStart = text.IndexOf(keyword);


    if (indexStart < 0)
    {
        Console.WriteLine("Could not find " + keyword + " entry in the file");
    }
    else
    {
        int indexEnd = text.Substring(indexStart).IndexOf("\r\n");
        string line = text.Substring(indexStart, indexEnd).Trim();
        value = line.Replace(keyword, " ").Trim();
    }

    return value;
}

List<string> stringparse(string str)
{
    string[] args = str.Trim().Split(' ');
    List<string> list = new List<string>();

    foreach (string arg in args)
    {
        if (arg.Trim().Length != 0)
        {
            list.Add(arg);
        }
    }

    return list;
}

3. 读取hdr文件的函数

View Code
//read header .hdr file
void ReadHDR(string path)
{
    string content = File.ReadAllText(path);

    info.FileName = path.Substring(0, path.LastIndexOf('.'));
    info.FormatVersion = fileparse("FormatVersion", content);
    info.Model = fileparse("Model", content);
    info.DataFormat = fileparse("DataFormat", content);
    info.GroupNumber = Convert.ToInt32(fileparse("GroupNumber", content));
    info.TraceTotalNumber = Convert.ToInt32(fileparse("TraceTotalNumber", content));
    info.DataOffset = Convert.ToInt32(fileparse("DataOffset", content));
    info.Endian = (fileparse("Endian", content) == "Big") ? WVFEndianType.Big : WVFEndianType.Little;
    info.Groups = new List<WVFGroup>();

    for (int i = 0; i < Info.GroupNumber; i++)
    {
        //Group
        WVFGroup group = new WVFGroup();
        int groupIndex = content.IndexOf("$Group" + (i+1).ToString());
        string groupContent = content.Substring(groupIndex);
        group.TraceNumber = Convert.ToInt32(fileparse("TraceNumber", groupContent));
        group.BlockNumber = Convert.ToInt32(fileparse("BlockNumber", groupContent));
        

        //Traces
        group.TraceName = stringparse(fileparse("TraceName", groupContent));
        group.BlockSize = stringparse(fileparse("BlockSize", groupContent)).ConvertAll<int>(x => Convert.ToInt32(x));
        group.VResolution = stringparse(fileparse("VResolution", groupContent)).ConvertAll<double>(x => Convert.ToDouble(x));
        group.VOffset = stringparse(fileparse("VOffset", groupContent)).ConvertAll<double>(x=>Convert.ToDouble(x));
        
        List<string> vDataType = stringparse(fileparse("VDataType", groupContent));
        group.VDataTypeByteFormat = new List<WVFByteFormatType>();
        group.VDataTypeByteNumber = new List<int>();

        /*
        % VDataType
        % ISn : n-byte signed integer
        % IUn : n-byte unsigned integer
        % FSn : n-byte signed real
        % FUn : n-byte unsigned real
        % Bm : m-byte logical data
        */
        foreach (string dt in vDataType)
        {
            int num = 0;
            switch (dt[0])
            {
                case 'I':  //integer numbers
                    switch (dt[1])
                    {
                        case 'S':
                            group.VDataTypeByteNumber.Add(Convert.ToInt32(dt.Substring(2)));
                            group.VDataTypeByteFormat.Add(WVFByteFormatType.IS);
                            break;
                        case 'U':
                            group.VDataTypeByteNumber.Add(Convert.ToInt32(dt.Substring(2)));
                            group.VDataTypeByteFormat.Add(WVFByteFormatType.IU);
                            break;
                        default:
                            group.VDataTypeByteNumber.Add(0);
                            group.VDataTypeByteFormat.Add(WVFByteFormatType.IS);
                            break;
                    }
                    break;
                case 'F':   //real numbers
                    switch (dt[1])
                    {
                        case 'S':
                            group.VDataTypeByteNumber.Add(Convert.ToInt32(dt.Substring(2)));
                            group.VDataTypeByteFormat.Add(WVFByteFormatType.FS);
                            break;
                        default:
                            group.VDataTypeByteNumber.Add(0);
                            group.VDataTypeByteFormat.Add(WVFByteFormatType.FS);
                            break;
                    }
                    break;
                default:
                    group.VDataTypeByteNumber.Add(0);
                    group.VDataTypeByteFormat.Add(WVFByteFormatType.IS);
                    break;
            }

        }

        group.VUnit = stringparse(fileparse("VUnit", groupContent));
        group.VPlusOverData = stringparse(fileparse("VPlusOverData", groupContent));
        group.VMinusOverData = stringparse(fileparse("VMinusOverData", groupContent));
        group.VIllegalData = stringparse(fileparse("VIllegalData", groupContent)).ConvertAll<double>(x => Convert.ToDouble(x));
        group.VMaxData = stringparse(fileparse("VMaxData", groupContent)).ConvertAll<double>(x => Convert.ToDouble(x));
        group.VMinData = stringparse(fileparse("VMinData", groupContent)).ConvertAll<double>(x => Convert.ToDouble(x));
        group.HResolution = stringparse(fileparse("HResolution", groupContent)).ConvertAll<double>(x => Convert.ToDouble(x));
        group.HOffset = stringparse(fileparse("HOffset", groupContent)).ConvertAll<double>(x => Convert.ToDouble(x));
        group.HUnit = stringparse(fileparse("HUnit", groupContent));
        group.Date = stringparse(fileparse("Date", groupContent));
        group.Time = stringparse(fileparse("Time", groupContent));
        group.TValues = new List<List<double>>();
        group.YValues = new List<List<double>>();

        Info.Groups.Add(group);
    }

}

4. 读取wvf文件的函数

View Code
//read data .wvf file
void ReadWVF(int groupIndex = 0, int traceIndex = 0, int blockIndex = 0)
{
    // Offset at beginning of binary file
    int offset = Info.DataOffset;

    // first for all groups before the selected group
    for (int i = 0; i < groupIndex; i++)
    {
        // for all traces and blocks in these groups...
        for (int j = 0; j < Info.Groups[i].TraceNumber; j++)
        {
            // add the offsets of all traces...
            offset += Info.Groups[i].BlockSize[j] * Info.Groups[i].BlockNumber * Info.Groups[i].VDataTypeByteNumber[j];
        }
    }


    // File Format Trace or Block saves traces and blocks in different
    // sequences:
    // Trace : Group1,Trace1,Block1, Group1,Trace1,Block2, ..., Group1,Trace1,BlockN, ..., Group1,Trace2,Block1, ..., Group2,Trace1,Block1, ..., GroupN,TraceN,BlockN (each block for a specific waveform)
    // Block : Group1,Trace1,Block1, Group1,Trace2,Block1, ..., Group1,TraceN,Block1, ..., Group1,Trace1,Block2, ..., Group2,Trace1,Block1, ..., GroupN,TraceN,BlockN (each block for a specific time interval).
    if (Info.DataFormat == "Trace")
    {
        //trace format:
        //%... add offsets of the traces before the selected trace in the selected group
        for (int i = 0; i < traceIndex; i++)
        {
            offset += Info.Groups[groupIndex].BlockSize[i] * Info.Groups[groupIndex].BlockNumber * Info.Groups[groupIndex].VDataTypeByteNumber[i];
        }
        //... and finally add offsets of the blocks in the selected trace in the selected group before the selected block
        offset += Info.Groups[groupIndex].BlockSize[traceIndex] * blockIndex * Info.Groups[groupIndex].VDataTypeByteNumber[traceIndex]; ;
    }
    else
    {
        //block format:
        //%... add offsets of the blocks before the selected block in the selected group
        for (int i = 0; i < blockIndex; i++)
        {
            for (int j = 0; j < Info.Groups[groupIndex].TraceNumber; j++)
            {
                offset += Info.Groups[groupIndex].BlockSize[j] * Info.Groups[groupIndex].VDataTypeByteNumber[j];
            }
        }
        //... and finally add offsets of the traces in the selected block in the selected group before the selected trace
        for (int i = 0; i < traceIndex; i++)
        {
            offset += Info.Groups[groupIndex].BlockSize[i] * Info.Groups[groupIndex].VDataTypeByteNumber[i];
        }
    }
    
    fs.Seek(offset, SeekOrigin.Begin);

    //number of data points stored in the selected trace in the file
    int nop = Info.Groups[groupIndex].BlockSize[traceIndex];
    
    WVFByteFormatType byteFormat = Info.Groups[groupIndex].VDataTypeByteFormat[traceIndex];
    int byteNum = Info.Groups[groupIndex].VDataTypeByteNumber[traceIndex];
    List<double> listY = new List<double>();
    List<double> listT = new List<double>();
    
    //read data values
    for (int i = 0; i < nop; i++)
    {
        byte[] bVal = reader.ReadBytes(byteNum);
        double dVal = 0;

        switch (byteFormat)
        {
            case WVFByteFormatType.IS:
                switch (byteNum)
                {
                    case 2:
                        switch (Info.Endian)
                        {
                            case WVFEndianType.Big:
                                dVal = BitConverter.ToInt16(bVal.Reverse().ToArray(), 0);
                                break;
                            default:
                                dVal = BitConverter.ToInt16(bVal, 0);
                                break;
                        }
                        break;
                    case 4:
                        switch (Info.Endian)
                        {
                            case WVFEndianType.Big:
                                dVal = BitConverter.ToInt32(bVal.Reverse().ToArray(), 0);
                                break;
                            default:
                                dVal = BitConverter.ToInt32(bVal, 0);
                                break;
                        }
                        break;
                    case 8:
                        switch (Info.Endian)
                        {
                            case WVFEndianType.Big:
                                dVal = BitConverter.ToInt64(bVal.Reverse().ToArray(), 0);
                                break;
                            default:
                                dVal = BitConverter.ToInt64(bVal, 0);
                                break;
                        }
                        break;
                    default:
                        break;
                }
                break;
            case WVFByteFormatType.IU:
                switch (byteNum)
                {
                    case 2:
                        switch (Info.Endian)
                        {
                            case WVFEndianType.Big:
                                dVal = BitConverter.ToUInt16(bVal.Reverse().ToArray(), 0);
                                break;
                            default:
                                dVal = BitConverter.ToUInt16(bVal, 0);
                                break;
                        }
                        break;
                    case 4:
                        switch (Info.Endian)
                        {
                            case WVFEndianType.Big:
                                dVal = BitConverter.ToUInt32(bVal.Reverse().ToArray(), 0);
                                break;
                            default:
                                dVal = BitConverter.ToUInt32(bVal, 0);
                                break;
                        }
                        break;
                    case 8:
                        switch (Info.Endian)
                        {
                            case WVFEndianType.Big:
                                dVal = BitConverter.ToUInt64(bVal.Reverse().ToArray(), 0);
                                break;
                            default:
                                dVal = BitConverter.ToUInt64(bVal, 0);
                                break;
                        }
                        break;
                    default:
                        break;
                }
                break;
            case WVFByteFormatType.FS:
                switch (byteNum)
                {
                    case 4:
                        switch (Info.Endian)
                        {
                            case WVFEndianType.Big:
                                dVal = BitConverter.ToSingle(bVal.Reverse().ToArray(), 0);
                                break;
                            default:
                                dVal = BitConverter.ToSingle(bVal, 0);
                                break;
                        }
                        break;
                    case 8:
                        switch (Info.Endian)
                        {
                            case WVFEndianType.Big:
                                dVal = BitConverter.ToDouble(bVal.Reverse().ToArray(), 0);
                                break;
                            default:
                                dVal = BitConverter.ToDouble(bVal, 0);
                                break;
                        }
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;

        }

        listY.Add(Info.Groups[groupIndex].VOffset[traceIndex] + Info.Groups[groupIndex].VResolution[traceIndex] * dVal);
        listT.Add(Info.Groups[groupIndex].HOffset[traceIndex] + Info.Groups[groupIndex].HResolution[traceIndex] * (1 + i));
    }

    Info.Groups[groupIndex].TValues.Add(listT);
    Info.Groups[groupIndex].YValues.Add(listY);

}

5. 读取wvf的类

View Code
public class WVFFile
{
    WVFInfo info = new WVFInfo();
    FileStream fs;
    BinaryReader reader;
    
    public WVFInfo Info
    {
        get { return info; }
        set { info = value; }
    }

    public WVFFile(string header, string file)
    {
       
        Info = new WVFInfo();
        ReadHDR(header);
        
        fs = new FileStream(file, FileMode.Open, FileAccess.Read);
        reader = new BinaryReader(fs);


        for(int i = 0; i < Info.GroupNumber; i++)
        {
            for (int j = 0; j < Info.Groups[i].TraceNumber; j++)
            {
                ReadWVF(i, j);
            }
        }

        reader.Close();
        fs.Close();
    }

}
原文地址:https://www.cnblogs.com/xpvincent/p/2844094.html