質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • C#

    7689questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

C#、OutOfMemoryExceptionが発生する(DXF読み込み)

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 519

ElecDove

score 230

いつもお世話になっております。

C#を使ってDXFの読み込み(パース?)をしたいと考えているのですが、
大量のエンティティ(線分、円弧等)を読み込んでいるためか、
OutOfMemoryExceptionが発生してしまいます

おそらく、根本的な作り方に問題があると思うのでどのような方向性で設計していけば数千~数万のエンティティをメモリ上に保持しても大丈夫か教えていただきたいです

(VSのデバッグ画面にある診断ツールでは、ちょっと大きなDXFファイルを読み込むとメモリ使用量が1GBをあっという間に超えてしまいます)

現在のコーディングでは、
あらかじめDXFの内部構造(に近い)の形をしたクラスをひな型として、
ファイルを読み込みながらそのひな型に実際のデータを肉付けしていく形にしています。

長いですが一応ひな型を示します。
あまりこのあたりの構造がよくわかっていないので意味不明なことになっているかもしれませんがご容赦ください
OutOfMemoryとは関係ない内容でも、アドバイスいただけると助かります。

変数の命名がアッパーだったりロワーだったりするのはまだあまり慣れてないからですすいません、、、少しずつ直していきます

        private class DxfFormat {
            public enum SectionIdList {
                HEADER,
                TABLES,
                BLOCKS,
                ENTITIES
            };

            public HeaderClass Header = new HeaderClass();
            public class HeaderClass {
                public enum VersionList { AC1003, AC1006, AC1009, AC1012, AC1014, AC1015, OTHER };
                public VersionList Version = VersionList.OTHER;

                public Point extmin = new Point();      //オブジェクト(図形)の最小値
                public Point extmax = new Point();      //オブジェクト(図形)の最大値
                public Point limmin = new Point();      //図面の最小値
                public Point linmax = new Point();      //図面の最大値
                public int dimscale;    //寸法の尺度
                public int PEXTMIN;     //ペーパー空間のオブジェクトの最小値
                public int PEXTMAX;     //ペーパー空間のオブジェクトの最大値
                public int DWGCODEPAGE; //図面のコードページ日本語はR13Jまで "dos932"、R14から"ANSI_932"です。
            }
            public TableClass table = new TableClass();
            public class TableClass {

                public class LineType {
                    public string Name;
                    public string Description;
                }

                public List<LineType> LineTypeList = new List<LineType>();
                public int numOfLayer;
                public string[] LayerName = new string[256];
                public int numOfLine;
            }

            public List<EntityClass> Entity = new List<EntityClass>();
            public class EntityClass {

                public EntityClassLine Line;
                public class EntityClassLine {
                    public PointF Start = new PointF();
                    public PointF End = new PointF();
                }

                public EntityClassArc Arc;
                public class EntityClassArc {
                    public PointF Center = new PointF();
                    public float Radius;
                    public float StartDegree;
                    public float EndDegree;
                }

                public EntityClassCircle Circle;
                public class EntityClassCircle {
                    public PointF Center = new PointF();
                    public float Radius;
                }

                public enum EntityList {
                    /// <summary>
                    /// 直線要素
                    /// </summary>
                    LINE,
                    /// <summary>
                    /// 円要素
                    /// </summary>
                    CIRCLE,
                    /// <summary>
                    /// 円弧
                    /// </summary>
                    ARC,
                    /// <summary>
                    ///
                    /// </summary>
                    POINT,
                    /// <summary>
                    /// 文字列 
                    /// </summary>       
                    TEXT
                };
                /// <summary>
                /// その図形の種類(線分/円/点…etc...)
                /// </summary>
                public EntityList Entity;
                /// <summary>
                /// その図形の描かれるレイヤー番号
                /// </summary>
                public string LayerName;
                /// <summary>
                /// その図形の描かれている色
                /// </summary>
                public int ColorName;
                /// <summary>
                /// その図形の描かれる線種
                /// </summary>
                public string LineType;
            }
        }

実際のファイル読み込み、解析処理は次のようになっています
(例として、ファイル中からLINEを見つけた後の処理のみ記載します)

//まずは、様々なエンティティを格納するオブジェクトを作って
DxfFormat.EntityClass ent = new DxfFormat.EntityClass();

                    if (DxfRaws[i].s == "LINE") {
                        i++;
          //今回はその中でも「線分」なので線分のインスタンスを作って
                        ent.Entity = DxfFormat.EntityClass.EntityList.LINE;
                        ent.Line = new DxfFormat.EntityClass.EntityClassLine();
          //開始点、終了点などの図形的情報を抽出、メンバに代入
                        while (DxfRaws[i].groupCode != 0) {
                            if (DxfRaws[i].groupCode == 6) {
                                ent.LineType = DxfRaws[i].s;
                            } else if (DxfRaws[i].groupCode == 8) {
                                ent.LayerName = DxfRaws[i].s;
                                //Console.WriteLine("Layer Name = " + DxfRaws[i].s);
                            } else if (DxfRaws[i].groupCode == 10) {
                                ent.Line.Start.X = float.Parse(DxfRaws[i].s);
                                //Console.WriteLine("  X-  " + DxfRaws[i].s);
                            } else if (DxfRaws[i].groupCode == 20) {
                                ent.Line.Start.Y = float.Parse(DxfRaws[i].s);
                                //Console.WriteLine("  Y-  " + DxfRaws[i].s);
                            } else if (DxfRaws[i].groupCode == 11) {
                                ent.Line.End.X = float.Parse(DxfRaws[i].s);
                                //Console.WriteLine("  -X  " + DxfRaws[i].s);
                            } else if (DxfRaws[i].groupCode == 21) {
                                ent.Line.End.Y = float.Parse(DxfRaws[i].s);
                                //Console.WriteLine("  -Y  " + DxfRaws[i].s);
                            }
                            i++;
                        }

//このあとで、dxfData.Entity.Add(ent);として、上で抽出したエンティティごとにリストに追加しています。
//dxfdataというのは、パースの完了したDXFデータを保存するオブジェクトです。

以下これの繰り返し&線分以外の図形に対しても行っています

根本的に何がまずいのでしょうか
よろしくお願いいたします

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

質問の内容と関係のないところがおかしくなっていたため発生していたようです
(無限ループ?)

お騒がせしました

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • C#

    7689questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。