211008 금
파일 입출력 연습하기
📌 이번에는 파일에 데이터를 저장하고 불러오는 방법을 보자!
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
path_provider: ^2.0.2
👉🏻 패키지 등록!
import 'package:flutter/material.dart';
class FileApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => _FileApp();
}
class _FileApp extends State<FileApp> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('File Example'),
),
body: Container(),
);
}
}
👉🏻 fileApp.dart라는 새로운 다트 파일을 만든다.
import 'dart:io';
import 'package:path_provider/path_provider.dart';
class _FileApp extends State<FileApp> {
int _count = 0;
@override
void initState() {
super.initState();
readCountFile();
}
void WriteCountFile(int count) async {
var dir = await getApplicationDocumentsDirectory();
File(dir.path + '/count.txt').writeAsStringSync(count.toString());
}
void readCountFile() async {
try {
var dir = await getApplicationDocumentsDirectory();
var file = await File(dir.path + '/count.txt').readAsString();
print(file);
setState(() {
_count = int.parse(file);
});
} catch (e) {
print(e.toString());
}
}
}
👉🏻 _FileApp 클래스에서 파일을 읽고 쓴다.
👉🏻 임시 디렉터리를 이용하기 위해서는 getTemporaryDirectory함수를 이용할 수 있다.
✍🏻 getApplicationDocumentsDirectory함수는 path_provider 패키지에 들어 있는 함수이다. 내부 저장소의 경로를 가져와 그곳에 파일을 읽거나 쓴다.
✍🏻 writeCountFile함수는 count값을 매개변수로 받아 count.txt 이름의 파일로 만들어 문자열 형태로 저장한다.
✍🏻 readCountFile함수는 파일을 다시 정수형으로 변환해 _count 변수에 저장한다.
body: Container(
child: Center(
child: Text(
'$_count',
style: TextStyle(fontSize: 40),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_count++;
});
writeCountFile(_count);
},
child: Icon(Icons.add),
),
);
👉🏻 버튼을 누를 때마다 _count값이 올라가고 writeCountFile 함수를 실행해 그 값을 저장한다.
import 'package:flutter/material.dart';
import 'fileApp.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: FileApp(),
);
}
}
👉🏻 main.dart에 연결
(영상)
좋아하는 과일 표시하기 - 파일 읽기
📌 데이터 양이 많고 자주 갱신될 필요가 없다면 앱 안에 미리 파일을 만들어 저장해두고 사용하는 방법도 있다.
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
path_provider: ^2.0.2
shared_preferences: 2.0.6
flutter:
uses-material-design: true
assets:
- repo/fruit.txt
👉🏻 fruit.txt 파일을 만들어 좋아하는 과일을 써둔다.
👉🏻 shared_preferences 패키지를 불러오고 fruit.txt 파일도 불러온다.
import 'package:shared_preferences/shared_preferences.dart';
Future<List<String>> readListFile() async {
List<String> itemList = new List.empty(growable: true)
var key = 'first';
SharedPreferences pref = await SharedPreferences.getInstance();
bool? firstCheck = pref.getBool(key);
var dir = await getApplicationDocumentsDirectory();
bool fileExist = await File(dir.path + '/fruit.txt').exists();
if (firstCheck == null || firstCheck == false || fileExist == false) {
pref.setBool(key, true);
var file =
await DefaultAssetBundle.of(context).loadString('repo/fruit.txt');
File(dir.path + '/fruit.txt').writeAsStringSync(file);
var array = file.split('\n');
for (var item in array) {
print(item);
itemList.add(item);
}
return itemList;
} else {
var file = await File(dir.path + '/fruit.txt').readAsString();
var array = file.split('\n');
for (var item in array) {
print(item);
itemList.add(item);
}
return itemList;
}
}
👉🏻 readFile함수는 애셋에 등록한 파일을 읽어 내부 저장소에서 다시 저장한다.
✍🏻 first 키를 이용해 bool값을 가져와 firstCheck 변수에 저장한다. 이 변수는 이후에 파일을 처음 열었는지 확인한다.
✍🏻 fileExist에는 지정한 경로에 파일이 있는지 확인한다. 있는지 여부에 따라 bool값이 결정된다.
✍🏻 위의 변수들을 확인해서 처음 열었거나, 파일이 없다면 공유 환경설정에서 true를 저장해 파일을 열었다고 기록하고 파일을 읽어 내부 저장소에 똑같은 파일을 만든다. 그리고 해당 파일 데이터를 리스트에 저장한다.
✍🏻 파일을 처음 연 것이 아니면 파일 데이터를 리스트로 만들어 반환하되 대상 파일을 내부 저장소의 fruit.txt 파일로 지정한다.
class _FileApp extends State<FileApp> {
int _count = 0;
List<String> itemList = new List.empty(growable: true);
TextEditingController controller = new TextEditingController();
@override
void initState() {
super.initState();
readCountFile();
initData();
}
void initData() async {
var result = await readListFile();
setState(() {
itemList.addAll(result);
});
}
👉🏻 앱을 실행하면 readListFile함수를 실행한다.
✍🏻 initState는 비동기 방식으로 처리할 수 없어 별도의 initData 함수를 만들어 비동기 처리를 한다. 이 함수는 readFile함수를 호출하고 setState로 리스트를 만든다.
Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
return Card(
child: Center(
child: Text(
itemList[index],
style: TextStyle(fontSize: 30),
),
),
);
},
itemCount: itemList.length,
),
)
✍🏻 Expanded 위젯: 남은 공간을 모두 사용하는 것이다. 이 코드는 텍스트 필드 이외의 나머지 부분을 ListView로 사용한다.
좋아하는 과일 추가하기 - 파일 쓰기
floatingActionButton: FloatingActionButton(
onPressed: () {
writeFruit(controller.value.text);
setState(() {
itemList.add(controller.value.text);
});
},
(...생략...)
void writeFruit(String fruit) async {
var dir = await getApplicationDocumentsDirectory();
var file = await File(dir.path + '/fruit.txt').readAsString();
file = file + '\n' + fruit;
File(dir.path + '/fruit.txt').writeAsStringSync(file);
}
👉🏻 버튼 누를 때만다 사용자가 등록한 과일이름을 내부 저장소의 fruit.txt 파일에 추가한다.
(영상)
내려받은 이미지를 로고로 사용하기
📌 인트로 화면을 바꿔보겠다! 이때 인트로 화면을 바꿀때마다 업데이트를 하는 것이 아닌 서버에서 이미지를 내려받는 방법을 보겠다!
import 'dart:io';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'main.dart';
class IntroPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => _IntroPage();
}
class _IntroPage extends State<IntroPage> {
Widget logo = Icon(
Icons.info,
size: 50,
);
@override
void initState() {
super.initState();
initData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: Column(
children: [
logo,
ElevatedButton(
onPressed: () {
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder:(context){
return MyHomePage(title: '')
}));
},
child: Text('다음으로 가기'),
)
],
mainAxisAlignment: MainAxisAlignment.center,
),
),
),
);
}
void initData() async {
var dir = await getApplicationDocumentsDirectory();
bool fileExist = await File(dir.path + '/myimage.jpg').exists();
if (fileExist) {
setState(() {
logo = Image.file(
File(dir.path + '/myimage.jpg'),
height: 200,
width: 200,
fit: BoxFit.contain,
);
});
}
}
}
👉🏻 내려받는 이미지를 자동으로 내부 저장소에 이미지 파일로 저장한다.
✍🏻 initData로 파일이 있는지 확인하고 logo 위젯에 이미지를 넣는다.
import 'introPage.dart';
home: IntroPage(),
👉🏻 메인 파일에 연결한다.
(영상)
'그 땐 App했지 > 그 땐 Flutter했지' 카테고리의 다른 글
[TAVE/Study]Do it! Flutter 10장 데이터베이스에 데이터 저장하기② (0) | 2021.10.13 |
---|---|
[TAVE/Study]Do it! Flutter 10장 데이터베이스에 데이터 저장하기① (0) | 2021.10.13 |
[TAVE/Study]Do it! Flutter 9장 내부 저장소 이용하기① (0) | 2021.10.11 |
[TAVE/Study]Do it! Flutter 8장 내비게이션 활용하기② (0) | 2021.10.06 |
[TAVE/Study]Do it! Flutter 8장 내비게이션 활용하기① (0) | 2021.10.06 |