DOBON.NETプログラミング道掲示板
(現在 過去ログ1 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■33274 / inTopicNo.1)  C# ファイルの重複チェック
  
□投稿者/ みすち 一般人(1回)-(2016/03/08(Tue) 17:17:21)
  • アイコン環境/言語:[windows7   C#.NET ] 
    分類:[.NET] 

    はじめまして。
    C#でのファイルの重複チェックについて質問させてください。
    重複チェック自体はよくあるのですが、処理が特殊(?)なためどうにもやりたいことができません。


    @ファイルよりデータを取得し、重複箇所を探したい(処理の中では削除しない)
    A重複チェックは特定文字列があった行のみ行いたい。(A HREFがある行のみチェックしたい)
    B削除ではないため重複があった場合、2つ目以降ではなく重複箇所をすべて取得したい。
    C階層構造や順序性があるためデータのソートはしたくない(したとしても元の並びに戻したい)
    D重複箇所がどのグループに属するのかも取得したい。

    以下のソースで、近いことはできましたが、
    下記処理では、最初の重複行を検知できません。
    どのようにすればよいでしょうか?
    もっと良い処理もあればご教授ください。



    *************************************************
    データサンプル
    *************************************************
    日付2000/11//11
    〜〜〜〜〜〜
    〜〜〜〜〜〜
    <g="A">
    <g="1">
    <A LOOP=〜〜〜〜>〜〜〜
    <g="2">
    <A HREF=〜〜〜〜>〜〜〜<A LOOP=〜〜〜〜>〜〜〜
    <g="B">
    <g="1">
    <A LOOP=〜〜〜〜>〜〜〜
    <g="2">
    <g="ASA">
    <A HREF=〜〜〜〜>〜〜〜
    <g="ESD">
    <A LOOP=〜〜〜〜>〜〜〜
    <g="2">
    <A LOCK=〜〜〜〜>〜〜〜

    *************************************************
    処理サンプル
    **************************************************
    //宣言
    string[,] dimv; //2次元配列
    List<string> list = new List<string>(); //空のListを作成する

    StreamReader sr = new StreamReader(@"ファイルパス", Encoding.GetEncoding("utf-8"));

    //ストーリームが終わるまで繰り返す
    while (sr.EndOfStream == false)
    {
    string line = sr.ReadLine();
    list.Add(line);
    }
    //ストリームが終わったら終了
    sr.Close();

    dimv = new string[list.Count, 4]; //1列目:番号、2列目行内容
    int num;
    num = 0;
    foreach (string s in list)
    {
    dimv[num, 0] = num.ToString(); //行番号
    dimv[num, 1] = s.TrimStart(); //内容
    dimv[num, 2] = 0.ToString(); //重複FLG、0=OK、1=重複
    if (0 <= dimv[num, 1].IndexOf("<A HREF="))
    {
    dimv[num, 3] = dimv[num, 1]; //重複チェックする場合は文字列格納
    }
    else
    { } //特になし

    //Writeは自動改行されない
    num = num + 1;
    }


    //重複チェック用
    var hashset = new HashSet<string>();
    for (int i = 0; i < dimv.GetLength(0); i++)
    {
    // 既に追加済みのキーが来た場合はfalseになる
    if (hashset.Add(dimv[i, 3]))
    {
    //OKの場合
    }
    else
    {
    //NGのばあい ・・・・ただ最初の1個は検知できない
    dimv[i, 2] = 1.ToString();
    }
    }


    // StreamWriter でファイルを初期化
    // System.IO.StreamWriter sw = new System.IO.StreamWriter(@"ファイルパス", true, System.Text.Encoding.GetEncoding("shift_jis"));
    System.IO.StreamWriter sw = new System.IO.StreamWriter(@"ファイルパス", true, System.Text.Encoding.GetEncoding("utf-8"));
    System.IO.StreamWriter sw2 = new System.IO.StreamWriter(@"ファイルパス", true, System.Text.Encoding.GetEncoding("utf-8"));

    for (int i = 0; i < dimv.GetLength(0); i++)
    {
    // sw.WriteLine(dimv[i, 1]);
    if("1" == dimv[i, 2])
    {
    sw2.WriteLine(dimv[i, 0] + dimv[i, 3]);
    }
    }

    // 閉じる (オブジェクトの破棄)
    sw.Close();
    sw2.Close();
    MessageBox.Show("出力完了");


    **************************************************
引用返信 削除キー/
■33275 / inTopicNo.2)  Re[1]: C# ファイルの重複チェック
□投稿者/ furu 一般人(4回)-(2016/03/08(Tue) 19:07:41)
  • アイコンこのソースを生かすのであれば、
    重複の文字列をList<String>などに保存し、
    あとから、重複の最初の1個にフラグを立ててけばいい。

    但し、プログラムに間違いがあるので
    直してからのほうがいいと思う。
引用返信 削除キー/
■33277 / inTopicNo.3)  Re[2]: C# ファイルの重複チェック
□投稿者/ みずち 一般人(1回)-(2016/03/09(Wed) 01:32:50)
  • アイコンNo33275に返信(furuさんの記事)
    > このソースを生かすのであれば、
    > 重複の文字列をList<String>などに保存し、
    > あとから、重複の最初の1個にフラグを立ててけばいい。
    >
    > 但し、プログラムに間違いがあるので
    > 直してからのほうがいいと思う。


    返信ありがとうございます。
    えーと、特段このソースを生かす必要はないです。
    「こんな感じかな」と私が手さぐり作ったものですので処理的にも無駄が多そうですので。
    もっと簡単な手法があるのであれば、教えていただきたいです。



    ちなみに、
    > 重複の文字列をList<String>などに保存し、
    > あとから、重複の最初の1個にフラグを立ててけばいい。
    というのは、重複チェック用のループの中で、List<String>に値を格納し、
    そのList<String>を再度ループして、配列dimvのなかをチェックということでいいのでしょうか?
    また処理が長くなりそう(><)


    > 但し、プログラムに間違いがあるので
    > 直してからのほうがいいと思う。
    プログラムの間違いは・・・すみません。
    自分のところでは時間はかかってもだいぶうまく動いたのですが・・・・もしかしたらコピペの際の注訳消したりした時に間違えたのかもです。



    一応、再ループかけて重複フラグを再度立てていきます。


    他にもっといい手法があれば教えていただけると助かります。

引用返信 削除キー/
■33281 / inTopicNo.4)  Re[3]: C# ファイルの重複チェック
□投稿者/ 朱鷺 一般人(1回)-(2016/03/09(Wed) 21:19:01)
  • アイコン
    No33277に返信(みずちさんの記事)
    あまり参考にならないかもしれませんがそれらしい動作をするものを作ってみました。
    --------------------------------------------------
    ・ChofukuCheck.cs
    using System.Collections.Generic;
    
    namespace ConsoleApplication4
    {
        public class ItemData
        {
            public int lineNum { get; }
            public string lineString { get; }
            public bool isChofuku { get; set; }
    
            public ItemData(int line,string str)
            {
                lineNum = line;
                lineString = str;
                isChofuku = false;
            }
            public bool ChofukuCheck(int ownNum,ref List<ItemData> iData)
            {
                bool chofuku = false;
                int ctr = 0;
                if(iData == null)
                {
                    return false;
                }
    
                foreach(ItemData i in iData)
                {
                    //HREFタグのみ検査対象とする
                    if(lineString.IndexOf("<A HREF=")>=0)
                    {
                        //自分自身以外の行の文字列に等しいものがある場合
                        if(ctr != ownNum && lineString == i.lineString)
                        {
                            iData[ctr].isChofuku = true;
                            chofuku = true;//自分自身の重複フラグをtrueにする
                        }
                    }
                    ctr++;
                }
                return chofuku;
            }
        }
    }
    ----------------------------------------------------------
    ・Program.cs
    using System;
    using System.Collections.Generic;
    using System.IO;
    
    namespace ConsoleApplication4
    {
        class Program
        {
            static void Main(string[] args)
            {
                List<ItemData> iData = new List<ItemData>();
                using (var fStream = new FileStream(@"F:\sample.txt", FileMode.Open, FileAccess.Read))
                {
                    using (var sReader = new StreamReader(fStream))
                    {
                        int ctr = 0;
                        while(sReader.EndOfStream == false)
                        {
                            iData.Add(new ItemData(ctr, sReader.ReadLine()));
                            iData[ctr].isChofuku = iData[ctr].ChofukuCheck(ctr, ref iData);
                            ctr++;
                        }
                    }
                }
                foreach(ItemData i in iData)
                {
                    Console.WriteLine(i.lineNum + "," + i.lineString + "," + i.isChofuku);
                }
                Console.ReadLine();
            }
        }
    }
    -------------------------------------------------------------------------
    重複チェックはこれでできるはずです、
    ただし、当初の質問にあった5つの要件のうち
    >D重複箇所がどのグループに属するのかも取得したい。
    この部分は考慮していません(「グループ」の仕様がデータサンプルから読み取れなかったため)。
    
    

引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -