質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

8回答

8333閲覧

既存のファイルを複数の指定の行数で分割保存する方法はありますか?

mendako

総合スコア8

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2017/10/25 20:34

編集2017/10/26 05:20

###前提・実現したいこと
膨大なデータ(excelで開けません)を指定の行で分割保存したいです。
その時、例えば、合計10000行のデータを、
1~1000行で1ファイル(1000行)、
1001行~3500行で1ファイル(2500行)、
3501行~7000行で1ファイル(3500行)、
7001行~10000行で1ファイル(3000行)、
といったようにばらばらの行数を指定して保存したいです。

###試したこと
ネットで調べたところ、指定の行で分割する方法はたくさん出てきました。
しかし、1種類の指定の行でしか分割できず、数種類の行数での分割方法は見当たりませんでした。
調べ不足でしたら申し訳ありません…。

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報
分割したいデータが膨大なため(2GB)、Excelでは開けません…。
また、分割指定をしたい行の種類も1000を超えているため、手作業では難しいです...。
分割したい行数のリストはあるのですが、どうすれば良いのか分からない状態です。

どなたか助言いただければ幸いです。
よろしくお願い致します。

###追記
皆さまご回答ありがとうございました。
本当に助かりました。
また何かありましたらよろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答8

0

昔つくったテキストファイルを10000行ずつに分割するツール
不便がないので昔から全然アップデートしてないので
ちょっと変な書き方もありますが、参考程度に

※1行目のデータをヘッダとして認識して、分割後の全てのファイルの
1行目にヘッダをつけています

「分割.vbs」という名前でテキスト保存して、そのアイコンに分割したい
テキストファイルをドロップして下さい

vbscript

1sub main() 2 set args= wscript.arguments 3 set oWSH =WScript.CreateObject("WScript.Shell") 4 set fs = CreateObject("Scripting.FileSystemObject") 5 if args.count=0 then 6 msgbox "ファイルを落としてください。" 7 exit sub 8 end if 9 10 set f=fs.getfile(args(0)) 11 fb=fs.getBasename(f) 12 ext=fs.getExtensionname(f) 13 fp=fs.GetParentFolderName(f)+"\" 14 if lcase(ext)<>"txt" then 15 msgbox "指定ファイルがちがう" 16 exit sub 17 end if 18 19 set otf = fs.OpenTextFile(f) 20 header=otf.readline() 21 j=1 22 Do While j < 99 23 Set myfile = fs.CreateTextFile(fp+fb+"-"+right(Cstr(100+j),2)+"."+ext, True) 24 myfile.WriteLine(header) 25 for i=0 to 9999 26 l=otf.readline() 27 myfile.WriteLine(l) 28 if otf.AtEndOfStream then 29 exit do 30 end if 31 next 32 myfile.Close 33 j=j+1 34 loop 35 otf.close 36 msgbox "ok!" 37end sub 38 39main()

投稿2017/10/26 04:40

yambejp

総合スコア114779

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

もし linux などの unix OS が使えるなら
sed や awk や perl などでスクリプトを書くか
もしくはこんな感じで

head 1000 hoge.txt > 1.txt #1~1000行で1ファイル(1000行) head -3500 hoge.txt | tail -2500 > 2.txt #1001行~3500行で1ファイル(2500行) head -7000 hoge.txt | tail -3500 > 3.txt #3501行~7000行で1ファイル(3500行) head -10000 hoge.txt | tail -3000 > 4.txt #7001行~10000行で1ファイル(3000行)

動作確認してませんが、少し調整すればいけるんじゃないかな?
--- 追記 ---

分割指定をしたい行の種類も1000を超えている

見逃してましたが、それならそのもととなるデータを読み込んで
上記を生成するスクリプトをなんかで作るという話になりますかね。

投稿2017/10/25 22:31

編集2017/10/25 22:37
takasima20

総合スコア7458

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mendako

2017/10/26 04:50

ご回答ありがとうございました。 headは頭からしか数えられないと思っていたので、行数指定ができることは初めて知りました。 勉強になりました。 分割指定をする部分を考えてみようと思います。
guest

0

500行ずつに分割して、あとで結合して希望の行数にすればいいと思います。

あるいは、Unix系のsedのようなツールだと、指定行だけ抜き出せます。
sed -n "1001,1500p" infile > outfile1001
とか。

投稿2017/10/25 21:52

otn

総合スコア84505

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mendako

2017/10/26 04:46

ご回答ありがとうございます。 sedを使えば抜きだし可能なのですね。勉強になりました。 当方が提示した例が悪くて大変申し訳ありません。 分割したい指定行は123、1809、などと切りが良い数字ではなく、本当にばらばらなのです。
cateye

2017/10/26 06:36

>本当にばらばら・・・であれば、行に含まれる情報で分割する方法がないのでしょうか?(たとえば、行に含まれる数値…あればですがw…が1000番台、2000番台など)であればもっとやり方があると思います。
otn

2017/10/26 11:50

切りの良い数字かどうかで、何かが変わるとお思いでしょうか? 変わりませんよ。そのまま書けばいいだけです。 sed -n "123,1809p" infile > outfile
cateye

2017/10/26 12:03

言葉が悪かったのかもしれません。私が言いたかったのは切り出す行のなかにキーになるデータがあるなら、行数を指定しなくても出力ファイルが切り替えられるのではないか?と言うことだったのですが。・・・例えば、試験の結果の点数によって生徒の情報を別ファイルに吐き出すといったようなことです。
otn

2017/10/26 12:08

あ、cateyeさんじゃなくて、質問者のmendakoさんへのコメントです。
cateye

2017/10/26 12:15

はやとちりしました^^; もうしわけないm(_"_)m
guest

0

ruby で書いてみました。

line_sep.rb

ruby

1## 使用例: 2## $ ruby line_sep.rb src.txt 10 20 3## src.txt を 1..10 行、11..20行、21..30 公卿、31.. 最終行 のファイルに分割する。 4# ファイル名は 0000000001.txt 0000000010.txt 0000000020.txt となる。 5# 出力ファイルは、確認なしに上書きされる。 6# 7def split_file(file_name, lines = [1], out_name_pattern) 8 out_f = File.open(format(out_name_pattern, 1), 'w') 9 File.open(file_name) do |file| 10 file.each_line.each_with_index do |line, index| 11 out_f.write(line) 12 13 next unless lines.include?(index + 1) 14 unless out_f.nil? 15 out_f.close 16 out_f = File.open(format(out_name_pattern, index + 1), 'w') 17 end 18 end 19 end 20 out_f.close if out_f.nil? 21end 22 23file_name = ARGV.shift # 読み込むファイル名 24lines = ARGV.map(&:to_i) # 各ファイルの終了行番号 25out_name_pattern = '%010d.txt' # 不出力ファイル名のパターン 26split_file(file_name, lines, out_name_pattern)

実行例:

# 10000 行のファイルを作る $ seq -w 1 10000 > hoge.txt # 作成したプログラムで 1000 行、2500行、3500行, 3000行で分割 $ ruby line_sep.rb hoge.txt 1000 3500 7000 # 分割結果のファイルの行数を確 $ $ wc -l 0*.txt 1000 0000000001.txt 2500 0000001000.txt 3500 0000003500.txt 3000 0000007000.txt 10000 total # 各ファイルの一行目を表示 $ $ head -n 1 0*.txt ==> 0000000001.txt <== 00001 ==> 0000001000.txt <== 01001 ==> 0000003500.txt <== 03501 ==> 0000007000.txt <== 07001 # 分割した結果をすべて連結させて、元の hoge.txt と比較 $ cat 0*.txt > cat.txt $ diff hoge.txt cat.txt $

投稿2017/10/29 11:18

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

既に回答がいろいろついてるので蛇足ですが、

分割数が多いことを鑑みると、分割時に何度も元のファイルをスキャンするより1回のスキャンで全ての分割ファイルを生成した方がいい気もするので、自分はtakasima20さん回答の「スクリプトを自動生成する」という考え方とawkを組み合わせたりします。

仮に分割位置指定ファイルが分割すべき最終行を1行ずつ並べたlines.txtに入っており、bigfile.csvの分割結果をdir/0001.csv,dir/0002.csvへ分割すると考えれば以下のような雰囲気です。

bash

1#!/bin/sh 2rm dir/* 2>/dev/null && true 3awk ' 4function genfn() { 5 ord++; return sprintf("dir/%04d.csv", ord) 6} 7{ print "NR <= "$1" { print>>\""genfn()"\"; next }" } 8END { 9 print "{ print>>\""genfn()"\"; next }" 10}' lines.txt > split.awk 11awk -f split.awk bigfile.csv

こうしたテキスト処理はやはりUnix系の環境でやりたくなります。既に回答されている方々も同様の想定をしておられますね。WindowsでもBash on Ubuntu on Windowsが使えるようになってきて今は大抵の汎用PC(Linuxそのもの、Macintosh, Windows)で手軽にこういう環境が使えるのではないでしょうか。

投稿2017/10/26 00:27

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Cのタグがついているので書いてみました。
コマンドラインから入力パラメーターを以下のようにして実行します。

実行モジュール名 <読み込みファイル名> <分割1開始行> <分割1終了行> <分割1出力ファイル名> ...

hoge.txt readfile.txt 1 1000 hoge1.txt 1001 3500 hoge2.txt 3501 7000 hoge3.txt 7001 10000 hoge4.txt

注意

  • 入力パラメーターのチェックは一切行っておりません。
  • 1行あたりの読み込みバッファは1024バイトしか確保しておりません。
  • ファイルオープン/クローズ/読み込み/書き込みのエラーチェックはしておりません。

c

1#include <stdio.h> 2 3int main(int argc, char**argv) 4{ 5 FILE *fr, *fw; 6 int i, st, ed; 7 char *fn; 8 char b[1024]; 9 char *ret; 10 long l; 11 12 // 読み込みファイルオープン 13 fr = fopen(argv[1], "r"); 14 if(!fr) return -1; 15 16 // パラメーター分ループ 17 for(i = 2, l = 1; i < argc; i+=3){ 18 // 開始行 19 st = atoi(argv[i]); 20 // 終了行 21 ed = atoi(argv[i + 1]); 22 // 出力ファイル名 23 fn = argv[i + 2]; 24 // ファイルオープン 25 fw = fopen(fn, "w"); 26 if(!fw) break; 27 // 読み込んで書き込むループ 28 for(; l <= ed; l++){ 29 // 読み込み 30 ret = fgets(b, sizeof(b), fr); 31 if(!ret) break; 32 if(l < st) continue; 33 // 書き込み 34 fputs(b, fw); 35 } 36 // 出力ファイルクローズ 37 fclose(fw); 38 if(!ret) break; 39 } 40 // 入力ファイルクローズ 41 fclose(fr); 42} 43

投稿2017/10/26 00:17

ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

取り合えず分割するところまでC++で組んでみましたが^^;・・・コンパイルは通してあります。

C++

1#include <iostream> 2#include <fstream> 3 4using namespace std; 5 6int main(int argc, char **argv) 7{ 8 if( argc != 3 ){ 9 return 1; 10 } 11 // 12 ifstream lnfile(argv[1]); 13 if( !lnfile ){ 14 return 2; 15 } 16 ifstream infile(argv[2]); 17 if( !infile ){ 18 return 3; 19 } 20 // 21 string lineno; 22 while( getline(lnfile,lineno)){ 23 int count= static_cast<int>(strtol(lineno.c_str(),0,10)); 24 string line; 25 // ここでファイルを書き出し用にオープン 26 for( int i= 0; i < count; i++ ){ 27 if(getline(infile,line)) { 28 cout << line << endl; // ファイル出力にする。 29 }else{ 30 return 4; 31 } 32 } 33 // ここでファイルをクローズ 34 } 35 // 36 return 0; 37} 38

使い方は、program 分割指定ファイル 分割したいファイル
※分割指定ファイルは、一行に分割したい行数1つのみ

投稿2017/10/26 00:03

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

なければ作ればよいのです。
JavaなのかCなのかMySQLなのかよくわかりませんが、手軽にJavaで作ると下記な感じでしょうか。
2GBのファイルでは試してませんが、多分動くのではないかと思います。

java

1import java.util.*; 2import java.io.*; 3 4public class Split { 5 6 private File srcfile; 7 private List<Integer> splist; 8 9 public static void main(String args[]) throws IOException { 10 File srcfile = new File(args[0]); 11 File splines = new File(args[1]); 12 13 Split sp = new Split(srcfile, splines); 14 sp.split(); 15 } 16 17 public Split(File srcfile, File splines) throws IOException { 18 this.srcfile = srcfile; 19 this.splist = new ArrayList<Integer>(); 20 21 try { 22 FileReader fr = new FileReader(splines); 23 BufferedReader br = new BufferedReader(fr); 24 25 String line; 26 while (null != (line = br.readLine())) { 27 int num = Integer.parseInt(line); 28 splist.add(num); 29 } 30 31 br.close(); 32 } catch (FileNotFoundException e) { 33 throw e; 34 } catch (IOException e) { 35 throw e; 36 } 37 } 38 39 public void split() throws IOException { 40 int sequence = 0; 41 try { 42 FileInputStream fis = new FileInputStream(this.srcfile); 43 InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); 44 BufferedReader br = new BufferedReader(isr); 45 46 for (int i : splist) { 47 PrintWriter pw = new PrintWriter(Integer.toString(sequence) + ".txt", "UTF-8"); 48 BufferedWriter bw = new BufferedWriter(pw); 49 50 int count = 0; 51 String line; 52 while (count < i && null != (line = br.readLine())) { 53 bw.write(line); 54 bw.newLine(); 55 count++; 56 } 57 bw.close(); 58 sequence++; 59 } 60 br.close(); 61 } catch (FileNotFoundException e) { 62 throw e; 63 } catch (IOException e) { 64 throw e; 65 } 66 } 67}

text

1$ seq -w 1 100000 > hoge 2$ for i in 1000 2000 3000 4000 5000 6000 7000 8000 9000; do echo $i >> fuga; done 3$ /opt/jdk-9/bin/java Split hoge fuga 4$ ls 50.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt Split.class Split.java fuga hoge 6$ wc -l *.txt 7 1000 0.txt 8 2000 1.txt 9 3000 2.txt 10 4000 3.txt 11 5000 4.txt 12 6000 5.txt 13 7000 6.txt 14 8000 7.txt 15 9000 8.txt 16 45000 合計

追記:

文字コードがUTF-8のファイルの読み書きに対応してみました(未検証)。

投稿2017/10/25 22:34

編集2017/10/26 04:56
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mendako

2017/10/26 04:43

ご丁寧な回答、ありがとうございました。 回答していただいた方法でやってみたところ、正しく分割できました。誠にありがとうございました。 しかし、元々のファイルの文字コードがutf-8で、分割後の文字コードがshift_jisなのですが、 文字コードutf-8の指定で分割することは可能でしょうか? 基本的な質問で申し訳ありません。また、助言いただければ幸いです。
退会済みユーザー

退会済みユーザー

2017/10/26 05:01

Javaだと文字コードはネックになりますね。 環境によらずUTF-8のファイルを扱うようにコードを修正してみました。 BufferedWriterは使う必要なかったかもしれませんが、直すのも手間なのでそのままにしてます。 問題あるようでしたら適宜修正ください。
mendako

2017/10/26 05:16

修正していただいたプログラムを実行したところ、当方が望んでいた結果が出力されました。 この度は早々のご回答を賜り、誠にありがとうございました。 また何かありましたら、よろしくお願い致します。
退会済みユーザー

退会済みユーザー

2017/10/26 05:21

うまく動いたようでよかったです。 WORAへの道は遠いですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問