# Split tile based map file into multiple files

I have a gigantic map file (1440x1080) that I wish to split into smaller files (45x45) for faster client reading. I plan to split offline (when running DEV server) so I am not too worried about speed. Picture the below as my source file:

5, 5, 5, 4, 5, 6, 5... 5
...
5, 6, 2, 44, 5, 66, 5... 5


I am getting the file to be slightly off towards the end - having trouble doing the math I suppose. I am totally open to changing the code, but here is what I had so far:

int filesAcross = mapWidth / 45;
int acrossCount = 0;
int filesDown = mapHeight / 45;
int downCount = 0;
int totalFileCount = filesAcross * filesDown;

//create a bunch of stringbuilder holders to split the large file into
StringBuilder[] sbGroundLayerHolders = new StringBuilder[totalFileCount];
for (int kk = 0; kk < totalFileCount; kk++) {
sbGroundLayerHolders[kk] = new StringBuilder();
}

int countt = 0;
while(scanner.hasNext()){
int fileCounter = (acrossCount / 45) + ((downCount / 45) * filesAcross);
//  LOGGER.info("fileCounter: " + fileCounter + "   acrossCount: " + acrossCount +
//"   downCount: " + downCount + "   countt: " + countt);
try {
sbGroundLayerHolders[fileCounter].append(scanner.nextShort());
sbGroundLayerHolders[fileCounter].append(",");
acrossCount++;

countt++;
} catch (InputMismatchException e){
scanner.nextLine();
downCount++;
acrossCount = 0;

countt++;
} catch (ArrayIndexOutOfBoundsException e){
LOGGER.fatal("Array Out of Bounds on ground Layer - count:" + countt, e);
System.exit(1);
}
}

//write array contents into files
for (int kk = 0; kk < totalFileCount; kk++) {
String s = sbGroundLayerHolders[kk].toString();
s = s.substring(0, s.length() - 1);
String[] sSplit = s.split(",");

StringBuilder q = new StringBuilder();
for (int jj = 0; jj < sSplit.length; jj++) {
q.append(sSplit[jj]);

if (((jj+1) % 45) == 0 && jj != 0) {
q.append(System.lineSeparator());
} else {
q.append(",");
}
}

LOGGER.info("map string(" + kk + "): " + q);
//createFileLocally(folderPath, filename, text);
}


Here is a sample image of what I want to do (smaller scale). Start with the big grid 6x6 and split into files 2x2.

• What are the specific symptoms of the file being "slightly off towards the end"? Do you get more chunk files than you expected? Fewer? Are some incomplete, or contain the wrong / invalid data? The more you can tell us about what's wrong, the faster it usually is to track down the cause. – DMGregory Jan 20 at 14:12
• It's really hard for me to see what is wrong because the files are so large with so many numbers. I do have a border wall around the map. It should be 90 the whole way around. On file 1 I see 90 on left side and top. On file 32 I see 90 44 tiles of the top, and the left wall. It should be all the way around the top and right wall. Not sure if that helps. – KisnardOnline Jan 20 at 19:29
• It does help. It sounds like an off-by-one error where you're computing the tile indices. Can you scale down your chunks to a size small enough to show a sample of your incorrect output inside your question? – DMGregory Jan 20 at 19:36

Here is how I solved this in case anyone else needs to do this:

int filesAcross = mapWidth / CHUNKSIZE;
int acrossCount = 0;
int filesDown = mapHeight / CHUNKSIZE;
int downCount = 0;
int totalFileCount = filesAcross * filesDown;

//create a bunch of stringbuilder holders to split the large file into
StringBuilder[] sbGroundLayerHolders = new StringBuilder[totalFileCount];
for (int kk = 0; kk < totalFileCount; kk++) {
sbGroundLayerHolders[kk] = new StringBuilder();
}

int countt = 0;
while(scanner.hasNextLine()){
String line = scanner.nextLine();
if (downCount != mapHeight - 1) {
line = line.substring(0, line.length() - 1); //to remove the last ,
}
String[] lineSplit = line.split(", ");
while(acrossCount < lineSplit.length) {
int fileCounter = (acrossCount / CHUNKSIZE) + ((downCount / CHUNKSIZE) * filesAcross);
//LOGGER.info("fileCounter: " + fileCounter + "   acrossCount: " + acrossCount +
//"   downCount: " + downCount + "   countt: " + countt);
Short t = Short.parseShort(lineSplit[acrossCount]);
//LOGGER.info("short: " + t);
sbGroundLayerHolders[fileCounter].append(t);
if (((acrossCount + 1) % CHUNKSIZE) == 0 && downCount != CHUNKSIZE - 1) {
sbGroundLayerHolders[fileCounter].append(System.lineSeparator());
} else {
if (acrossCount != lineSplit.length - 1) {
sbGroundLayerHolders[fileCounter].append(",");
}
}
acrossCount++;

countt++;
}
downCount++;
acrossCount = 0;
}

• This answer would be even better if it included a plain language description of what you changed and why, so users don't have to infer this from a line-by-line diff of your code. – DMGregory Jan 21 at 20:00
• I changed it completely. – KisnardOnline Jan 22 at 4:19