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

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

ただいまの
回答率

91.02%

  • Java

    12131questions

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

  • MySQL

    5091questions

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

  • C

    3069questions

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

  • Excel

    1215questions

    Excelは、マイクロソフト社が開発しているデータ集計や分析を行う表計算ソフトの一つです。文書作成や表計算、資料作成などの多彩な機能を備えており、統合パッケージであるMicrosoft Officeに含まれています。

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

解決済

回答 8

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 644

mendako

score 2

前提・実現したいこと

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

試したこと

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

補足情報(言語/FW/ツール等のバージョンなど)

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

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

追記

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 8

+2

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/26 13:46

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

    キャンセル

  • 2017/10/26 15:36

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

    キャンセル

  • 2017/10/26 20:50

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

    キャンセル

  • 2017/10/26 21:03

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

    キャンセル

  • 2017/10/26 21:08

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

    キャンセル

  • 2017/10/26 21:15

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

    キャンセル

+2

もし 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/26 13:50

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

    キャンセル

+2

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

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

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

sub main()
  set args= wscript.arguments
  set oWSH =WScript.CreateObject("WScript.Shell")
  set fs = CreateObject("Scripting.FileSystemObject")
  if args.count=0 then
    msgbox "ファイルを落としてください。"
    exit sub
  end if

  set f=fs.getfile(args(0))
  fb=fs.getBasename(f)
  ext=fs.getExtensionname(f)
  fp=fs.GetParentFolderName(f)+"\"
  if lcase(ext)<>"txt" then
     msgbox "指定ファイルがちがう"
     exit sub
  end if

  set otf = fs.OpenTextFile(f)
  header=otf.readline()
  j=1
  Do While j < 99
    Set myfile = fs.CreateTextFile(fp+fb+"-"+right(Cstr(100+j),2)+"."+ext, True)
    myfile.WriteLine(header)
    for i=0 to 9999
      l=otf.readline()
      myfile.WriteLine(l)
      if otf.AtEndOfStream then
        exit do
      end if
    next
    myfile.Close
    j=j+1
  loop
  otf.close
  msgbox "ok!"
end sub

main()

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+1

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

import java.util.*;
import java.io.*;

public class Split {

   private File srcfile;
   private List<Integer> splist;

   public static void main(String args[]) throws IOException {
      File srcfile = new File(args[0]);
      File splines = new File(args[1]);

      Split sp = new Split(srcfile, splines);
      sp.split();
   }

   public Split(File srcfile, File splines) throws IOException {
      this.srcfile = srcfile;
      this.splist = new ArrayList<Integer>();

      try {
         FileReader fr = new FileReader(splines);
         BufferedReader br = new BufferedReader(fr);

         String line;
         while (null != (line = br.readLine())) {
            int num = Integer.parseInt(line);
            splist.add(num);
         }

         br.close();
      } catch (FileNotFoundException e) {
         throw e;
      } catch (IOException e) {
         throw e;
      }
   }

   public void split() throws IOException {
      int sequence = 0;
      try {
         FileInputStream fis = new FileInputStream(this.srcfile);
         InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
         BufferedReader br = new BufferedReader(isr);

         for (int i : splist) {
            PrintWriter pw = new PrintWriter(Integer.toString(sequence) + ".txt", "UTF-8");
            BufferedWriter bw = new BufferedWriter(pw);

            int count = 0;
            String line;
            while (count < i && null != (line = br.readLine())) {
               bw.write(line);
               bw.newLine();
               count++;
            }
            bw.close();
            sequence++;
         }
         br.close();
      } catch (FileNotFoundException e) {
         throw e;
      } catch (IOException e) {
         throw e;
      }
   }
}
$ seq -w 1 100000 > hoge
$ for i in 1000 2000 3000 4000 5000 6000 7000 8000 9000; do echo $i >> fuga; done
$ /opt/jdk-9/bin/java Split hoge fuga
$ ls
0.txt  1.txt  2.txt  3.txt  4.txt  5.txt  6.txt  7.txt  8.txt  Split.class  Split.java  fuga  hoge
$ wc -l *.txt
  1000 0.txt
  2000 1.txt
  3000 2.txt
  4000 3.txt
  5000 4.txt
  6000 5.txt
  7000 6.txt
  8000 7.txt
  9000 8.txt
 45000 合計

追記:

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/26 13:43

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

    キャンセル

  • 2017/10/26 14:01

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

    キャンセル

  • 2017/10/26 14:16

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

    キャンセル

  • 2017/10/26 14:21

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

    キャンセル

+1

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

#include <iostream>
#include <fstream>

using namespace std;

int main(int argc, char **argv)
{
    if( argc != 3 ){
        return 1;
    }
    //
    ifstream lnfile(argv[1]);
    if( !lnfile ){
        return 2;
    }
    ifstream infile(argv[2]);
     if( !infile ){
        return 3;
    }
    //
    string lineno;
    while( getline(lnfile,lineno)){
        int count= static_cast<int>(strtol(lineno.c_str(),0,10));
        string line;
        // ここでファイルを書き出し用にオープン
        for( int i= 0; i < count; i++ ){
            if(getline(infile,line))            {
                cout << line << endl; // ファイル出力にする。
            }else{
                return 4;
            }
        }
        // ここでファイルをクローズ
    }
    //
    return 0;
}


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

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バイトしか確保しておりません。
  • ファイルオープン/クローズ/読み込み/書き込みのエラーチェックはしておりません。
#include <stdio.h>

int main(int argc, char**argv)
{
    FILE *fr, *fw;
    int i, st, ed;
    char *fn;
    char b[1024];
    char *ret;
    long l;

    // 読み込みファイルオープン
    fr = fopen(argv[1], "r");
    if(!fr) return -1;

    // パラメーター分ループ
    for(i = 2, l = 1; i < argc; i+=3){
        // 開始行
        st = atoi(argv[i]);
        // 終了行
        ed = atoi(argv[i + 1]);
        // 出力ファイル名
        fn = argv[i + 2];
        // ファイルオープン
        fw = fopen(fn, "w");
        if(!fw) break;
        // 読み込んで書き込むループ
        for(; l <= ed; l++){
            // 読み込み
            ret = fgets(b, sizeof(b), fr);
            if(!ret) break;
            if(l < st) continue;
            // 書き込み
            fputs(b, fw);
        }
        // 出力ファイルクローズ
        fclose(fw);
        if(!ret) break;
    }
    // 入力ファイルクローズ
    fclose(fr);
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

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

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

ruby で書いてみました。

line_sep.rb

##  使用例:
##  $ ruby line_sep.rb src.txt 10 20
##     src.txt を 1..10 行、11..20行、21..30 公卿、31.. 最終行 のファイルに分割する。
#      ファイル名は 0000000001.txt    0000000010.txt 0000000020.txt となる。
#   出力ファイルは、確認なしに上書きされる。
#
def split_file(file_name, lines = [1], out_name_pattern)
  out_f = File.open(format(out_name_pattern, 1), 'w')
  File.open(file_name) do |file|
    file.each_line.each_with_index do |line, index|
      out_f.write(line)

      next unless lines.include?(index + 1)
      unless out_f.nil?
        out_f.close
        out_f = File.open(format(out_name_pattern, index + 1), 'w')
      end
    end
  end
  out_f.close if out_f.nil?
end

file_name = ARGV.shift  # 読み込むファイル名
lines = ARGV.map(&:to_i) # 各ファイルの終了行番号
out_name_pattern = '%010d.txt' # 不出力ファイル名のパターン
split_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
$

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 91.02%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Java

    12131questions

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

  • MySQL

    5091questions

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

  • C

    3069questions

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

  • Excel

    1215questions

    Excelは、マイクロソフト社が開発しているデータ集計や分析を行う表計算ソフトの一つです。文書作成や表計算、資料作成などの多彩な機能を備えており、統合パッケージであるMicrosoft Officeに含まれています。