【C言語】ファイルの入出力(csvの読み込み)

## csv読み込みでのファイルの入出力例
```C++:example.c
#include <stdio.h>
#include <string.h>

int main(void)
{
    FILE* fp = NULL; // 操作するファイルのポインタ
    char buffer[1024];

    // ファイルを開く
    // fopen_s(FILE*のアドレス, ファイル名, オープンモード)
    fopen_s(&fp, "test.csv", "r");
    if (fp == NULL)
    {
        // ファイルの読み込みに失敗
        perror("fopen");
        return 1;
    }

    // ファイルを1行ずつ取得する
    // fgets(保存先, 要素数, FILE*)
    while (fgets(buffer, sizeof(buffer), fp) != NULL) // char* == NULLまでループ
    {
        // 読み込んだ一行をカンマで分割して処理
        // strtok_s(分割対象の文字列, 区切り文字, 分割情報)
        char* context = buffer;
        char* token = strtok_s(buffer, ",", &context);
        while (token != NULL)
        {
            printf("%s\n", token);
            token = strtok_s(NULL, ",", &context);
        }
    }

    // ファイルを閉じる
    fclose(fp);

	return 0;
}
```

- 1文字ずつ読み込む
```C
// 一文字ずつ読み込む
char c;
while ((c = fgetc(FILE*)) != EOF) // EOF(EndOfFile)になるまでループ
{
    // 処理
}
```

- データのサイズ分読み取る
```C
fread(バッファ, サイズ(byte), データの数, FILE*);
```

- データのサイズ分書き込む
```C
fwrite(バッファ, サイズ(byte), データの数, FILE*);
```

|モード|用途|ファイルがあるとき|ファイルがないとき|
|-|-|-|-|
|"r"|読み込み|正常|エラー(NULL)|
|"w"|書き込み|サイズを0に(上書き)|新規作成|
|"a"|追加読み込み|最後に追加|新規作成|
|"r+"|読み込みと書き込み|正常|エラー(NULL)|
|"w+"|書き込みと読み込み|サイズを0に(上書き)|新規作成|
|"a+"|読み込みと追加書き込み|最後に追加する|新規作成|

### C++の場合
```C++:example.cpp
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

int main(void)
{
    std::string line;

    // ファイルを開く
    std::ifstream ifs("test.csv");
    if (!ifs)
    {
        // ファイルの読み込みに失敗
        std::perror("ifstream");
        return 1;
    }

    // ファイルを1行ずつ取得する
    while (std::getline(ifs, line))
    {
        // 読み込んだ一行をカンマで分割して処理
        std::istringstream ss(line);
        std::string cell;
        while (std::getline(ss, cell, ','))
        {
            std::cout << cell << std::endl;
        }
    }
}
```

- 1文字ずつ読み込む
```C++
// 一文字ずつ読み込む
char c;
while (ifs.get(c))
{
    // 処理
}
```

- ファイルの読み込みの別例
```C++
#include<filesystem>

// ファイルを読み込む
const size_t filesize = std::filesystem::file_size(filename);
std::vector<char> buffer(filesize);
file.read(buffer.data(), filesize);
file.close();
```

### UnityC#の場合
```C#:example.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;

public class Example : MonoBehavior
{
    // Start is called before the first frame update
    void Start()
    {
        // CSVの読み込み
        TextAsset csvFile = Resources.Load("test") as TextAsset; // ResourcesにあるCSVファイルを格納
        StringReader reader = new StringReader(csvFile.text); // TextAssetをStringReaderに変換
        List<string[]> csvData = new List<string[]>(); // CSVファイルの中身を入れるリスト
        while (reader.Peek() != -1)
        {
            string line = reader.ReadLine(); // 1行ずつ読み込む
            csvData.Add(line.Split(',')); // csvDataリストに追加する
        }

        // string型以外の値(int, floatなど)にしたい場合
        // 型.Parse(csvData[?行目][?列])
    }
}
```

## 暗号化と復号化(排他的論理和暗号)
- **暗号化**
元のデータ(平文)に処理を施し、別なデータに変換する

- **復号化**
暗号化されたデータを元のデータに戻す(**復号**)

生のデータでは触り放題なので**鍵をかけ**、外部から操作しにくくする

```C:example.c
#include <stdio.h>

int main(void)
{
    int hp = 10;
    int atk = 1;
    printf("体力 : %d, 攻撃力 : %d\n", hp, atk);

    // 暗号化(施錠する)
    int key = 0xAA;
    hp ^= key;
    atk ^= key;
    printf("暗号化された体力 : %d, 暗号化された攻撃力 : %d\n", hp, atk);

    // 復号化(解錠する)
    hp ^= key;
    atk ^= key;
    printf("体力 : %d, 攻撃力 : %d\n", hp, atk);

    return 0;
}
```

## 執筆者メモ
自身は、ゲーム制作中にこれらのエンジン / ツール部分?を触る機会が少なく、
経験がかなり少ないので、参考程度に留めるようにお願いします...