ファイルのコピー

ファイルのコピー

C# のソースファイルを読んで、
HTMLファイルに変換するツールを C# で作成する。

最初は、単純にファイルを読んで書くだけのプログラムを作成し、
段階的に機能を拡張していく。

まず、呼ばれるたびに1文字づつ読み込んで返す関数 getChar
呼ばれるたびに1文字づつ書き込む関数 putChar
それらを組み合わせて、File を Copy する 関数 charcopy を作成する。

charcopy

1文字づつ読み込んで1文字づつ書き込む関数 charcopy を作成する。


//*********************************************************************
// ファイルのコピー
//*********************************************************************
public void charcopy(Reader reader, Writer writer)
{
//ファイルの終わりまで、1文字ずつ読んで
char c;
while ((c = reader.getChar()) != EOF)
{
//1文字づつ書き込む
writer.putChar(c);
}
}

getChar

呼ばれるたびに1文字づつ読み込んで返す関数 getChar を作成する。

実際のファイルからの読み込みは行単位で行う。

読み込んだ文字列をreadBufferに保存しておき、
現在の読み込み位置をreadIndexに保存しておく。

読み込み位置の初期値は、-1にしておき、読み込み位置が-1ということは、
読み込んだ文字列が空っぽであることを意味する。

現在位置が-1の時に呼び出されると、次の行を読み込み、
現在位置を0に設定する。

読み込んだ文字列から1文字返し、現在位置を1つ進める。
現在位置が、読み込んだ文字列の長さと同じになったら、改行コードを返し、
現在位置を-1に設定する。

ファイルの終わりに達したら、EOFを返す。


//********************************************************
// 入力ファイル用クラス
//********************************************************
public class Reader
{
private const char EOF = '\0';
private const char NEWLINE = '\n';

private System.IO.StreamReader reader;
private bool IsOpen = false;
private string fileName = "";
private string readBuffer = "";
private int readIndex = -1;

//****************************************************
// 初期化
//****************************************************
public Reader(string fileName)
{
this.fileName = fileName;
}
//****************************************************
// 終了
//****************************************************
~Reader()
{
Close();
}
public void Close()
{
//OPENしてたら
if (IsOpen)
{
//CLOSEする
reader.Close();
reader = null;
IsOpen = false;
}
}

//****************************************************
// 入力ファイルから1文字ずつ読む
//****************************************************
public char getChar()
{
//まだOPENしてなかったら
if (!IsOpen)
{
//OPENする
reader = new System.IO.StreamReader(fileName, System.Text.Encoding.GetEncoding("Shift_JIS"));
IsOpen = true;
}

//現在位置が初期化されていたら (読み込み用バッファが空っぽ)
if (readIndex < 0)
{
//次の行を読む
readBuffer = reader.ReadLine();

//次の行がなければ
if (readBuffer == null)
{
return EOF;
}

//現在位置を行の先頭に位置づける
readIndex = 0;
}

//現在位置が読み込み用バッファの最後に達したら
if (readIndex >= readBuffer.Length)
{
//現在位置を初期化する
readIndex = -1;
//改行コードを返す
return NEWLINE;
}

//読み込み用バッファから1文字返して、現在位置を1つ進める
return readBuffer[readIndex++];
}
}

putChar

呼ばれるたびに1文字づつ書き込む関数 putChar を作成する。

実際の書き込みは行単位で行う。
呼ばれるたびに、渡された文字をwriteBufferに追加して行き、
改行コードが渡されたら、ファイルに書き込む。


//********************************************************
// 出力ファイル用クラス
//********************************************************
public class Writer
{
private const char NEWLINE = '\n';

private System.IO.StreamWriter writer;
private bool IsOpen = false;
private string fileName = "";
private string writeBuffer = "";

//****************************************************
// 初期化
//****************************************************
public Writer(string fileName)
{
this.fileName = fileName;
}
//****************************************************
// 終了
//****************************************************
~Writer()
{
Close();
}
public void Close()
{
//OPENしてたら
if (IsOpen)
{
//書き込み用バッファに何か残っていたら
if (writeBuffer != "")
{
//書き込み用バッファの内容を書き込み、バッファをクリアする
writer.WriteLine(writeBuffer);
writeBuffer = "";
}

//CLOSEする
writer.Close();
writer = null;
IsOpen = false;
}
}

//****************************************************
// 出力ファイルに1文字ずつ書く
//****************************************************
public void putChar(char c)
{
//まだOPENしてなかったら
if (!IsOpen)
{
//OPENする
writer = new System.IO.StreamWriter(fileName, false, System.Text.Encoding.GetEncoding("Shift_JIS"));
IsOpen = true;
}

//改行コードが渡されたら
if (c == NEWLINE)
{

//書き込み用バッファの内容を書き込み、バッファをクリアする
writer.WriteLine(writeBuffer);
writeBuffer = "";
}
else
{
//書き込み用バッファに1文字追加する
writeBuffer += c;
}
}
}