파일 입출력
파일 쓰기
File.WriteAllLines(filepath,lines); // filepath에 lines를 모두 출력한다.
//using System.IO; 네임스페이스 적어주어야 File의 메소드를 쓸 수 있습니다.
static void Main(string[] args)
{
string filePath = "example.txt"; //파일이 생성될 경로 정의
//파일에 쓰여질 문자열 배열을 정의
string[] lines = { "First Line", "Second Line", "Third Line" };
//문자열의 배열을 "example.txt"라는 새 파일에 씁니다.
//파일이 이미 존재하는 경우 덮어씁니다.
File.WriteAllLines(filePath, lines);
Console.WriteLine("File written successfully.");
}
파일의 경로 지정 방법
파일이 저장될 경로를 지정한다. 상대적 경로 또는 절대적 경로로 작성할 수 있다.
string filePath = "example.txt"; // 상대 경로
//절대 경로를 지정하는 방법
//string filePath = "C:/Users/example.txt";
//string filePath = "C:\\Users\\example.txt";
//string filePath = @"C:\Users\example.txt";
파일 읽기
- StreamReader를 사용하기 (한 줄씩 읽기)
//파일이 읽혀질 파일 경로를 정의합니다.
string filePath = "example.txt";
//파일을 읽기 전에 파일이 존재하는지 확인합니다.
if (File.Exists(filePath))
{
//파일을 읽기 위한 스트림리더
//using 문은 StreamReader가 올바르게 폐기되도록 합니다.
//따라서 sr는 해당 스코프를 벗어나면 사용할 수 없습니다.
using (StreamReader sr = new StreamReader(filePath))
{
//파일을 한줄 씩 Read합니다.
string line = sr.ReadLine();
//파일의 끝에 도달할 때까지 각 줄을 읽습니다.
while (line != null)
{
//읽어온 줄을 콘솔에 출력합니다.
Console.WriteLine(line);
//그 다음 라인을 읽어옵니다.
line = sr.ReadLine();
}
}
}
else
{ //파일을 찾을 수 없음을 사용자에게 알립니다.
Console.WriteLine("File not Found");
}
- 위와 아래 코드는 동일하게 파일을 읽어온 후 출력하는 기능을 한다.
- File.ReadAllLines() 이용하기 (모든 줄 읽어들이기)
//파일이 읽혀질 파일 경로를 정의합니다.
string filePath = "example.txt";
//파일을 읽기 전에 파일이 존재하는지 확인합니다.
if (File.Exists(filePath))
{
//파일의 모든 줄을 문자열 배열로 읽어들입니다.
string[] lines = File.ReadAllLines(filePath);
//배열의 각 줄을 순회하며 콘솔에 읽어온 파일을 출력합니다.
for (int index = 0; index < lines.Length; ++index)
Console.WriteLine(lines[index]);
// == foreach (string line in lines) Console.WriteLine(line);
}
else
{
Console.WriteLine("File not Found");
}
🎓 새로운 지식 :: 파일에 추가 쓰기 (File.AppendAllText, FileAppendAllLines)
string filePath = "example.txt"; //파일 경로 정의
string newLine = "Fourth line"; //파일에 추가될 새 줄을 정의
//filepath에다가 newLine 데이터를 추가한다. (파일이 존재하지 않으면 생성됨)
File.AppendAllText(filePath, newLine + Environment.NewLine);
//Environment.NewLine이 \n와 같은 역할을 하기 때문에 줄바꿈이 됨.
//File.AppendAllText(filePath, newLine)로 작성하면 줄바꿈이 되지 않음.
//여러 줄 newLines 데이터를 추가한다.
string[] newLines = { "5th line", "6th line" };
File.AppendAllLines(filePath, newLines);
Console.WriteLine("Line appended Successfully.");
C# collection
Array 배열은 데이터가 고정적인 메모리공간에 연속적으로 시퀀스하게 들어간다.
인덱스를 통해 랜덤액세스가 가능하여 시간복잡도가 O(1)인 상수시간이며 굉장히 빠른 접근시간을 가진다.
Array에서는 데이터 삽입, 삭제 시 메모리공간을 broken하고 다른 메모리 공간에 다시 순차적으로 정리한다. 즉, heap에서 메모리 재할당이 일어나기 때문에 굉장히 큰 오버헤드가 발생하므로 런타임에 삽입, 삭제가 불가능하며 C#에서는 아예 Insert나 Append가 되지 않는다. 주로 가변하지 않는 자료에 대해 사용한다.
C# collection는 자료구조, 자바의 제네릭과 비슷하며 다이아몬드 연산자(꺾쇠 괄호)를 사용한다.
static void ListCollection() //리스트
{
List<int> numbers = new List<int>() { 1, 2, 3, 4, 5 };
numbers.Add(6);
numbers.RemoveAt(3); //3번째 요소를 삭제합니다.
foreach (var number in numbers)
Console.WriteLine(number);
}
static void DictionaryCollection() //딕셔너리 : map, table, 키와 밸류를 갖는다.
{
Dictionary<string,int> dictionary = new Dictionary<string,int>();
dictionary["hi"] = 1;
foreach (var item in dictionary)
Console.WriteLine(item);
}
💡질문 :: List<>도 배열처럼 인덱스가 있나요?
⇒ List<>도 배열처럼 인덱스가 존재해 랜덤액세스, 시간복잡도 O(1)의 상수시간 액세스가 가능합니다. 따라서 List<>에도 for 반복문을 통해 각 요소에 접근하는 방법을 사용할 수 있습니다.
💡질문 :: 한 리스트에 자료형이 서로 다른 데이터들도 넣을 수 있나요? array에 int도 담고 string도 담으려면 어떻게 하나요?
⇒ List의 타입을 <object>로 하면 가능합니다.
+ 강사님 코멘트 : List<object> 또는 ArrayList를 사용하면 여러 유형을 넣을 수 있습니다. ArrayList를 추천하지 않는 이유는 박싱 과정에서의 메모리 부담이 크기 때문입니다.
boxing/unboxing은 주로 다른 언어끼리 데이터를 주고받을 때 일어나는 과정입니다.
이 boxing 과정이 ArrayList가 서로 다른 타입의 데이터를 배열에 가져오는 과정에서도 발생하면서 메모리 부담을 주게 됩니다. 따라서 무작위 타입을 다룰거라면 List<object>를 사용하는 것을 더 추천합니다.
LINQ (Language Integrated Queary)
LINQ (Language Integrated Queary) [링크] : 데이터를 쿼리로 작성할 수 있다. 즉, 쿼리문을 이용하여 데이터를 조작할 수 있게 해준다.
- Where : 조건을 만족하는 요소를 필터링
- Select : 컬렉션의 각 요소를 특정 형식으로 변환.
- OrderBy, OrderByDescending : 컬렉션을 정렬
- GroupBy : 컬렉션의 요소를 그룹화
- Join : 두 컬렉션을 조인
- Sum, Max, Min, Average : 집계 함수
- Count : 요소 개수를 계산
💡 질문 :: var는 어떤 자료형인가요?
⇒ C#의 var는 다른 언어의 auto와 비슷하다고 생각하면 쉽습니다. 개발자가 명시적으로 변수의 데이터타입을 정하는 것이 아니라, 할당된 값을 기반으로 데이터타입을 추론하여 컴파일 타임에 자동으로 지정합니다.
static void LinqToObject()
{
//예제 데이터 소스
List<int> numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//짝수만 골라 필터링
var evenNumbers = from number in numbers
where number % 2 == 0 //number%2 == 0인 요소를 필터링
select number;
//메서드 구문을 사용하여 LINQfunction을 쓰면
//var evenNumbers = numbers.Where(e => e%2 == 0).Select(e=>e);와 같다.
//결과 출력
Console.WriteLine("Even numbers : ");
foreach (var num in evenNumbers)
{
Console.WriteLine(num);
}
}
- 위 내용을 LINQ를 사용하지 않고 for문으로 작성하면 아래와 같이 작성할수 있다.
static void LinqToObject()
{
//예제 데이터 소스
List<int> numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var oddNumbers = new List<int>();
foreach (var number in numbers)
{
if(number % 2 != 0) //짝수가 아닌 수(홀수)만 추가
oddNumbers.Add(number);
}
Console.WriteLine("Odd numbers : ");
foreach (var number in oddNumbers)
{
Console.WriteLine(number);
}
}
- 복잡한 형식을 사용하는 LINQ
struct Student
{
//프로퍼티
public int Id { get; set; } //기본적으로는 zero, 초기화는 생성자에서 하면 된다.
//private int id;
//public int Id { get{return id;} private set{id=value*1000;} } : 외부에서 set하지 못함.
public string Name { get; set; }
public int Age { get; set; }
}
void StudentCulling()
{
List<Student> students = new List<Student>(){
new Student { Id = 1, Name = "Cheolsu", Age = 36 }
new Student { Id = 2, Name = "Cheolsu2", Age = 18 }
};
// 아래 방법으로도 리스트 요소를 추가할 수 있다.
students.Add(new Student { Id = 3, Name = "Cheolsu3", Age = 45 });
//나이에 따라 학생 정렬
var sortedStudents = students.OrderBy(student => student.Age).ToList();
Console.WriteLine("Sorted by Age : "); //출력
foreach(var student in sortedStudents)
Console.WriteLine($"Name : {student.Name}, Age : {student.Age}");
//학생들의 평균 나이 계산
double averageAge = students.Average(student => student.Age);
Console.WriteLine($"Average age : {averageAge}");
//18세 이상인 학생만 추출
var adultCheolsu = from student in students
where student.Age >= 18
select student;
foreach (var student in adultCheolsu)
{
Console.WriteLine("id : {0}\n name : {1}\n age : {2}\n", student.Id, student.Name, student.Age);
//문자열 보간을 사용하여 아래와 같이 작성할 수 있다.
//Console.WriteLine($"id : {student.Id}, name : {student.Name}, age : {student.Age}");
}
}
🎓새로운 지식 :: 프로퍼티
클래스는 외부에서 직접 멤버변수에 접근하는 것을 제어하기 위해 멤버변수를 은닉하고, getID(), setID()등 특정 메서드를 작성하여 이를 통해 변수에 접근하도록 하는데,
C#에서는 이러한 프로퍼티를 간소화하여 int ID { get; set; } 처럼 사용할 수 있으며 이들 get{ }, set{ }을 접근자라고 한다.
참고 자료👍 :: 문자열 보간
https://woojoolog.tistory.com/4#google_vignette
public class Student{ ... }
static void Main(string[] args)
{
//예제 데이터 소스
List<Student> students = new List<Student>();
students.Add(new Student { Id = 1, Name = "Cheolsu", Age = 36 });
students.Add(new Student { Id = 1, Name = "Cheolsu2", Age = 18 });
students.Add(new Student { Id = 3, Name = "Cheolsu3", Age = 45 });
//학생 아이디별 그룹핑
var result = from student in students
group student by student.Id;
// 메서드 구문 LINQ 그룹핑
// var groups = students.GroupBy(e => e.Id);
//결과 출력
foreach (var group in result)
{
Console.WriteLine(group.Key);
foreach (var item in group)
{
Console.WriteLine("\t {0}", item.Name);
}
}
}
'UNITY > 유니티게임스쿨' 카테고리의 다른 글
Unity 비동기 프로그래밍 :: Node.js 설치, 간단한 비동기 서버 구축 (0) | 2024.06.07 |
---|---|
[유니티게임스쿨 TIL] 유니티 기본 :: 캐릭터 애니메이션 설정하기, 트리거 활용하기 (0) | 2024.06.05 |
[유니티게임스쿨 TIL] 유니티 기본 :: 프리팹과 오브젝트, 캐릭터 이동, 점프 기능 추가하기 (1) | 2024.06.03 |
[유니티게임스쿨 TIL] 유니티 기본 :: 유니티 설치와 인터페이스 이해 (0) | 2024.05.31 |
[유니티게임스쿨 TIL] C# 기초 문법 이해 :: 재귀 함수, 연산자, 클래스와 인터페이스 (0) | 2024.05.30 |