0
# File System and Assets
1
2
The GWT backend provides browser-compatible file system access with limitations imposed by web security. It supports internal assets, local storage files, and integrates with the asset preloading system for optimal web performance.
3
4
## Core File System Classes
5
6
### GwtFiles { .api }
7
8
```java
9
public class GwtFiles implements Files {
10
// File handle creation
11
public FileHandle internal(String path);
12
public FileHandle external(String path); // Not supported, throws exception
13
public FileHandle absolute(String path); // Not supported, throws exception
14
public FileHandle local(String path);
15
public FileHandle classpath(String path);
16
17
// Storage availability
18
public boolean isExternalStorageAvailable(); // Always returns false
19
public boolean isLocalStorageAvailable(); // Checks localStorage support
20
21
// Storage paths
22
public String getLocalStoragePath();
23
public String getExternalStoragePath(); // Not supported
24
}
25
```
26
27
### GwtFileHandle { .api }
28
29
```java
30
public class GwtFileHandle extends FileHandle {
31
// File operations
32
public boolean exists();
33
public boolean isDirectory();
34
public FileHandle child(String name);
35
public FileHandle parent();
36
public FileHandle sibling(String name);
37
38
// File information
39
public String name();
40
public String nameWithoutExtension();
41
public String extension();
42
public String path();
43
public String pathWithoutExtension();
44
45
// Type checking
46
public FileType type();
47
public boolean isInternal();
48
public boolean isExternal();
49
public boolean isAbsolute();
50
public boolean isLocal();
51
52
// Reading operations
53
public InputStream read();
54
public BufferedInputStream read(int bufferSize);
55
public Reader reader();
56
public Reader reader(String charset);
57
public String readString();
58
public String readString(String charset);
59
public byte[] readBytes();
60
61
// Length and modification
62
public long length();
63
public long lastModified();
64
65
// Writing operations (limited support)
66
public OutputStream write(boolean append);
67
public OutputStream write(boolean append, int bufferSize);
68
public Writer writer(boolean append);
69
public Writer writer(boolean append, String charset);
70
public void writeString(String string, boolean append);
71
public void writeString(String string, boolean append, String charset);
72
public void writeBytes(byte[] bytes, boolean append);
73
public void writeBytes(byte[] bytes, int offset, int length, boolean append);
74
75
// Directory operations (limited support)
76
public FileHandle[] list();
77
public FileHandle[] list(FilenameFilter filter);
78
public FileHandle[] list(String suffix);
79
public boolean deleteDirectory();
80
public void emptyDirectory();
81
public void emptyDirectory(boolean preserveTree);
82
83
// File operations
84
public void copyTo(FileHandle dest);
85
public void moveTo(FileHandle dest);
86
public boolean delete();
87
public boolean mkdirs();
88
89
// Temporary files (not supported)
90
public File file(); // Throws UnsupportedOperationException
91
}
92
```
93
94
## File Types and Storage
95
96
### Internal Files (Assets)
97
98
Internal files are read-only assets bundled with the application:
99
100
```java
101
// Access bundled game assets
102
FileHandle textureFile = Gdx.files.internal("images/player.png");
103
FileHandle audioFile = Gdx.files.internal("audio/background.ogg");
104
FileHandle dataFile = Gdx.files.internal("data/levels.json");
105
106
// Read asset content
107
String levelData = Gdx.files.internal("data/level1.json").readString();
108
byte[] imageData = Gdx.files.internal("images/sprite.png").readBytes();
109
110
// Assets must be included in the preloader for web deployment
111
// See preloader.md for asset management details
112
```
113
114
### Local Storage Files
115
116
Local files use browser localStorage for persistent data:
117
118
```java
119
// Save game progress to localStorage
120
FileHandle saveFile = Gdx.files.local("save/progress.json");
121
saveFile.writeString("{\"level\": 5, \"score\": 1000}", false);
122
123
// Load saved data
124
if (saveFile.exists()) {
125
String saveData = saveFile.readString();
126
// Parse and use save data
127
}
128
129
// Local storage has size limitations (typically 5-10MB)
130
// Store only essential data like saves, preferences, etc.
131
```
132
133
### File Type Restrictions
134
135
```java
136
// Web security restrictions limit file system access:
137
138
// ✓ Supported: Read internal assets
139
FileHandle asset = Gdx.files.internal("data/config.txt");
140
String config = asset.readString();
141
142
// ✓ Supported: Read/write local storage
143
FileHandle local = Gdx.files.local("settings.json");
144
local.writeString("{\"volume\": 0.8}", false);
145
146
// ✗ NOT supported: External file access
147
try {
148
FileHandle external = Gdx.files.external("documents/file.txt");
149
// Throws UnsupportedOperationException
150
} catch (UnsupportedOperationException e) {
151
System.out.println("External files not supported on web");
152
}
153
154
// ✗ NOT supported: Absolute file paths
155
try {
156
FileHandle absolute = Gdx.files.absolute("/home/user/file.txt");
157
// Throws UnsupportedOperationException
158
} catch (UnsupportedOperationException e) {
159
System.out.println("Absolute paths not supported on web");
160
}
161
```
162
163
## Usage Examples
164
165
### Asset Loading
166
167
```java
168
public class AssetManager {
169
private Texture playerTexture;
170
private Sound jumpSound;
171
private String levelData;
172
173
public void loadAssets() {
174
// Load textures (must be preloaded)
175
playerTexture = new Texture(Gdx.files.internal("sprites/player.png"));
176
177
// Load audio (must be preloaded)
178
jumpSound = Gdx.audio.newSound(Gdx.files.internal("audio/jump.wav"));
179
180
// Load text data
181
levelData = Gdx.files.internal("data/level1.json").readString();
182
}
183
184
public void disposeAssets() {
185
if (playerTexture != null) playerTexture.dispose();
186
if (jumpSound != null) jumpSound.dispose();
187
}
188
}
189
```
190
191
### Save System Implementation
192
193
```java
194
public class SaveSystem {
195
private static final String SAVE_FILE = "game_save.json";
196
197
public static class SaveData {
198
public int level;
199
public int score;
200
public boolean[] unlockedLevels;
201
public float musicVolume;
202
public float sfxVolume;
203
}
204
205
public void saveProgress(SaveData data) {
206
try {
207
// Convert save data to JSON
208
String json = convertToJson(data);
209
210
// Write to local storage
211
FileHandle saveFile = Gdx.files.local(SAVE_FILE);
212
saveFile.writeString(json, false);
213
214
System.out.println("Game saved successfully");
215
} catch (Exception e) {
216
System.err.println("Failed to save game: " + e.getMessage());
217
}
218
}
219
220
public SaveData loadProgress() {
221
try {
222
FileHandle saveFile = Gdx.files.local(SAVE_FILE);
223
224
if (saveFile.exists()) {
225
String json = saveFile.readString();
226
return parseFromJson(json);
227
} else {
228
// Return default save data
229
return createDefaultSave();
230
}
231
} catch (Exception e) {
232
System.err.println("Failed to load game: " + e.getMessage());
233
return createDefaultSave();
234
}
235
}
236
237
public boolean hasSavedGame() {
238
return Gdx.files.local(SAVE_FILE).exists();
239
}
240
241
public void deleteSave() {
242
FileHandle saveFile = Gdx.files.local(SAVE_FILE);
243
if (saveFile.exists()) {
244
saveFile.delete();
245
}
246
}
247
248
private SaveData createDefaultSave() {
249
SaveData data = new SaveData();
250
data.level = 1;
251
data.score = 0;
252
data.unlockedLevels = new boolean[10];
253
data.unlockedLevels[0] = true; // First level unlocked
254
data.musicVolume = 0.8f;
255
data.sfxVolume = 1.0f;
256
return data;
257
}
258
259
private String convertToJson(SaveData data) {
260
// Implement JSON serialization
261
// Can use libGDX Json class or manual string building
262
return "{}"; // Placeholder
263
}
264
265
private SaveData parseFromJson(String json) {
266
// Implement JSON deserialization
267
// Can use libGDX Json class or manual parsing
268
return new SaveData(); // Placeholder
269
}
270
}
271
```
272
273
### Configuration File Management
274
275
```java
276
public class ConfigManager {
277
private static final String CONFIG_FILE = "config.properties";
278
private Properties config;
279
280
public void loadConfig() {
281
config = new Properties();
282
283
try {
284
FileHandle configFile = Gdx.files.local(CONFIG_FILE);
285
if (configFile.exists()) {
286
// Load existing config
287
String configText = configFile.readString();
288
// Parse properties format
289
parseProperties(configText);
290
} else {
291
// Create default config
292
setDefaultConfig();
293
saveConfig();
294
}
295
} catch (Exception e) {
296
System.err.println("Failed to load config: " + e.getMessage());
297
setDefaultConfig();
298
}
299
}
300
301
public void saveConfig() {
302
try {
303
String configText = propertiesToString();
304
FileHandle configFile = Gdx.files.local(CONFIG_FILE);
305
configFile.writeString(configText, false);
306
} catch (Exception e) {
307
System.err.println("Failed to save config: " + e.getMessage());
308
}
309
}
310
311
public String getString(String key, String defaultValue) {
312
return config.getProperty(key, defaultValue);
313
}
314
315
public int getInt(String key, int defaultValue) {
316
try {
317
return Integer.parseInt(config.getProperty(key, String.valueOf(defaultValue)));
318
} catch (NumberFormatException e) {
319
return defaultValue;
320
}
321
}
322
323
public float getFloat(String key, float defaultValue) {
324
try {
325
return Float.parseFloat(config.getProperty(key, String.valueOf(defaultValue)));
326
} catch (NumberFormatException e) {
327
return defaultValue;
328
}
329
}
330
331
public boolean getBoolean(String key, boolean defaultValue) {
332
return Boolean.parseBoolean(config.getProperty(key, String.valueOf(defaultValue)));
333
}
334
335
public void setString(String key, String value) {
336
config.setProperty(key, value);
337
}
338
339
public void setInt(String key, int value) {
340
config.setProperty(key, String.valueOf(value));
341
}
342
343
public void setFloat(String key, float value) {
344
config.setProperty(key, String.valueOf(value));
345
}
346
347
public void setBoolean(String key, boolean value) {
348
config.setProperty(key, String.valueOf(value));
349
}
350
351
private void setDefaultConfig() {
352
config = new Properties();
353
config.setProperty("music_volume", "0.8");
354
config.setProperty("sfx_volume", "1.0");
355
config.setProperty("fullscreen", "false");
356
config.setProperty("difficulty", "normal");
357
}
358
359
private void parseProperties(String text) {
360
// Implement properties file parsing
361
String[] lines = text.split("\n");
362
for (String line : lines) {
363
line = line.trim();
364
if (!line.isEmpty() && !line.startsWith("#")) {
365
int equals = line.indexOf('=');
366
if (equals > 0) {
367
String key = line.substring(0, equals).trim();
368
String value = line.substring(equals + 1).trim();
369
config.setProperty(key, value);
370
}
371
}
372
}
373
}
374
375
private String propertiesToString() {
376
StringBuilder sb = new StringBuilder();
377
for (Object key : config.keySet()) {
378
sb.append(key).append("=").append(config.getProperty((String) key)).append("\n");
379
}
380
return sb.toString();
381
}
382
}
383
```
384
385
### Asset Validation
386
387
```java
388
public class AssetValidator {
389
public static boolean validateAssets() {
390
String[] requiredAssets = {
391
"images/player.png",
392
"images/enemy.png",
393
"audio/background.ogg",
394
"audio/jump.wav",
395
"data/levels.json"
396
};
397
398
boolean allAssetsExist = true;
399
400
for (String assetPath : requiredAssets) {
401
FileHandle asset = Gdx.files.internal(assetPath);
402
if (!asset.exists()) {
403
System.err.println("Missing required asset: " + assetPath);
404
allAssetsExist = false;
405
}
406
}
407
408
return allAssetsExist;
409
}
410
411
public static void listAvailableAssets(String directory) {
412
try {
413
FileHandle dir = Gdx.files.internal(directory);
414
if (dir.exists() && dir.isDirectory()) {
415
FileHandle[] files = dir.list();
416
System.out.println("Assets in " + directory + ":");
417
for (FileHandle file : files) {
418
System.out.println(" " + file.path());
419
}
420
}
421
} catch (Exception e) {
422
System.err.println("Cannot list directory: " + directory);
423
}
424
}
425
}
426
```
427
428
## Web-Specific File Considerations
429
430
### Storage Limitations
431
432
```java
433
// Browser localStorage typically has 5-10MB limit
434
public class StorageManager {
435
public static boolean checkStorageSpace() {
436
try {
437
// Test write to check available space
438
FileHandle testFile = Gdx.files.local("test_space.tmp");
439
testFile.writeString("test", false);
440
testFile.delete();
441
return true;
442
} catch (Exception e) {
443
System.err.println("Storage space check failed: " + e.getMessage());
444
return false;
445
}
446
}
447
448
public static long estimateStorageUsage() {
449
// Estimate current localStorage usage
450
// This is approximate as there's no direct API
451
try {
452
FileHandle[] localFiles = Gdx.files.local("").list();
453
long totalSize = 0;
454
for (FileHandle file : localFiles) {
455
totalSize += file.length();
456
}
457
return totalSize;
458
} catch (Exception e) {
459
return -1; // Unable to estimate
460
}
461
}
462
}
463
```
464
465
### Asset Preloading Integration
466
467
```java
468
// Assets must be preloaded for web deployment
469
// This is handled automatically by the preloader system
470
// See preloader.md for complete details
471
472
public void loadPreloadedAssets() {
473
// These assets must be listed in assets.txt for preloader
474
Texture texture = new Texture(Gdx.files.internal("images/sprite.png"));
475
Sound sound = Gdx.audio.newSound(Gdx.files.internal("audio/effect.wav"));
476
String data = Gdx.files.internal("data/config.json").readString();
477
478
// Assets not in preloader will fail to load or cause delays
479
}
480
```