可変配列を持つ構造体をファイル出力するには?


ひろちゃん  2010-10-22 05:37:55  No: 147163

構造体の配列のサイズが2パターンある場合にうまい具合にファイル出力する方法はありませんか?

<VBFixedArray(xx)>を使って2パターンの構造体を作り、関数を完全に分けてしまえば問題なく処理できるのですが、スマートじゃないように感じてしまい悩んでいます。

やりたいことは
    Public Structure FILE_LAYOUT
        <VBFixedStringAttribute(10)> Dim DataType As String
        Dim TransitTime() As Short
        Dim y() As Short
    End Structure

    Public Function makeFile(ByRef InputData As String) As String
        Dim FileName As String
        Dim tmpArray() As String
        Dim FileData As FILE_LAYOUT
        Dim DataSize As Integer
        Dim i As Integer
        Dim fn As Integer

        tmpArray = InputData.Split(",")
        If tmpArray(0).Equals("SMALL") Then
            DataSize = 9
            FileName = "small.dat"
        Else
            DataSize = 19
            FileName = "large.dat"
        End If
        ReDim FileData.TransitTime(DataSize)
        ReDim FileData.y(DataSize)

        FileData.DataType = tmpArray(0)
        For i = 0 To DataSize
            FileData.TransitTime(i) = tmpArray(2 * i + 1)
            FileData.y(i) = tmpArray(2 * i + 2)
        Next

        fn = FreeFile()
        FileOpen(fn, FileName, OpenMode.Random, , , Len(FileData))
        FilePut(fn, FileData)
        FileClose(fn)

        Return FileName
    End Function
です。

このソースでは
System.IO.IOException: レコード長が正しくありません。
になってしまいます。


天才レオ  2010-10-22 07:10:38  No: 147164

あらら、構文の基礎ができてないな。
入門からはじめましょう。


ひろちゃん  2010-10-25 20:44:52  No: 147165

とりあえずバイト配列にしてみました

    Public Structure FILE_LAYOUT
        <VBFixedStringAttribute(10)> Dim DataType As String
        Dim TransitTime() As Short
        Dim y() As Short
    End Structure

    Public Function makeFile(ByRef InputData As String) As String
        Dim FileName As String
        Dim tmpArray() As String
        Dim FileData As FILE_LAYOUT
        Dim DataSize As Integer
        Dim i As Integer
        Dim fn As Integer
        Dim writeArray() As Byte
        Dim binWriter As BinaryWriter

        tmpArray = InputData.Split(",")
        If tmpArray(0).Equals("SMALL") Then
            DataSize = 9
            FileName = "small.dat"
        Else
            DataSize = 19
            FileName = "large.dat"
        End If
        ReDim FileData.TransitTime(DataSize)
        ReDim FileData.y(DataSize)

        FileData.DataType = tmpArray(0)
        For i = 0 To DataSize
            FileData.TransitTime(i) = tmpArray(2 * i + 1)
            FileData.y(i) = tmpArray(2 * i + 2)
        Next

        If DataSize = 9 Then
            ReDim writeArray(49)
        Else
            ReDim writeArray(89)
        End If
        binWriter = New BinaryWriter(New IO.MemoryStream(writeArray))
        Try
            binWriter.Write(System.Text.Encoding.GetEncoding(932).GetBytes(FileData.DataType.PadRight(10)))
            For i = 0 To DataSize
                binWriter.Write(FileData.TransitTime(i))
            Next
            For i = 0 To DataSize
                binWriter.Write(FileData.y(i))
            Next
        Finally
            binWriter.Close()
        End Try

        fn = FreeFile()
        FileOpen(fn, FileName, OpenMode.Random, , , writeArray.Length)
        FilePut(fn, writeArray)
        FileClose(fn)

        Return FileName
    End Function


ひろちゃん  2010-10-26 23:55:11  No: 147166

C言語だとこんな感じかな

struct FILE_LAYOUT {
  char *DataType;
  short *TransitTime;
  short *y;
};

char *makeFile(char *InputData)
{
  char *FileName;
  char *p1, p2;
  struct FILE_LAYOUT FileData;
  int DataCount;
  int i;
  int FileSize;
  FILE *fp;

  p1 = strtok(InputData, ",");
  if( strcmp(p1, "SMALL") == 0 ) {
    DataCount = 10;
    FileSize = 50;
    FileName = "small.dat";
  } else {
    DataCount = 20;
    FileSize = 90;
    FileName = "large.dat";
  }
  FileData.DataType = malloc(FileSize);
  FileData.TransitTime = FileData.DataType + 10;
  FileData.y = FileData.TransitTime + DataCount;

  strcpy(FileData.DataType, p1);
  for( i = 0; i < DataCount; i++ ) {
    p1 = strtok(NULL, ",");
    FileData.TransitTime[i] = (short)atoi(p1);
    p1 = strtok(NULL, ",");
    FileData.y[i] = (short)atoi(p1);
  }

  fp = fopen(FileName, "wb");
  fwrite(FileData.DataType, 1, FileSize, fp);
  fclose(fp);

  free(FileData.DataType);

  return FileName;
}

VBでできないかな〜
インターフェース使ったらどうだろう?
あとでためしてみよう


あはは  2010-10-28 06:35:10  No: 147167

Dim TransitTime() As Short
        Dim y() As Short

あはは。

ムリするなよ(笑)

本を買え。
買っても理解できなきゃ、絶対にコンピュター言語攻略はムリ。
子供の頃に勉強したことがなかろう?

毒毒しい発言だが、正しい解答である。

以上。


ひろちゃん  2010-10-28 18:38:24  No: 147168

インターフェース全然使えない

    Public Interface IFileLayout
        Property DataType() As String
        Property TransitTime(ByVal index As Integer) As Short
        Property y(ByVal index As Integer) As Short
    End Interface

    Public Class SmallLayout
        Implements IFileLayout
        <VBFixedStringAttribute(10)> Dim _DataType As String
        <VBFixedArray(9)> Dim _TransitTime() As Short
        <VBFixedArray(9)> Dim _y() As Short

        Public Property DataType() As String Implements IFileLayout.DataType
            Get
                Return _DataType
            End Get
            Set(ByVal value As String)
                _DataType = value
            End Set
        End Property

        Public Property TransitTime(ByVal index As Integer) As Short Implements IFileLayout.TransitTime
            Get
                Return _TransitTime(index)
            End Get
            Set(ByVal value As Short)
                _TransitTime(index) = value
            End Set
        End Property

        Public Property y(ByVal index As Integer) As Short Implements IFileLayout.y
            Get
                Return y(index)
            End Get
            Set(ByVal value As Short)
                y(index) = value
            End Set
        End Property

        Public Sub New()
            ReDim _TransitTime(9)
            ReDim _y(9)
        End Sub
    End Class

    Public Function makeFile(ByRef InputData As String) As String
        Dim FileName As String
        Dim tmpArray() As String
        Dim FileData As IFileLayout
        Dim DataSize As Integer
        Dim i As Integer
        Dim fn As Integer

        tmpArray = InputData.Split(",")
        If tmpArray(0).Equals("SMALL") Then
            DataSize = 9
            FileName = "small.dat"
            FileData = New SmallLayout
        Else
            DataSize = 19
            FileName = "large.dat"
            'FileData = New LargeLayout
        End If

        FileData.DataType = tmpArray(0)
        For i = 0 To DataSize
            FileData.TransitTime(i) = tmpArray(2 * i + 1)
            FileData.y(i) = tmpArray(2 * i + 2)
        Next

        fn = FreeFile()
        FileOpen(fn, FileName, OpenMode.Random, , , Len(FileData))
        FilePut(fn, FileData)
        FileClose(fn)

        Return FileName
    End Function

Set(ByVal value As Short)のところで
System.StackOverflowExceptionが発生してしまった
なぜスタックオーバーフローなのか?
インターフェースってどういう構造なのか?
いろいろ疑問が出てしまった


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加