วิธีที่เร็วที่สุดในการคัดลอกไฟล์ใน node.js


488

โครงการที่ฉันกำลังทำงาน (node.js) แสดงถึงการดำเนินการจำนวนมากด้วยระบบไฟล์ (การคัดลอก / อ่าน / เขียน ฯลฯ ) ฉันต้องการทราบว่าวิธีใดเร็วที่สุดและฉันยินดีที่จะรับคำแนะนำ ขอบคุณ


42
มันเป็นคำถามที่ดีแม้ว่ามันจะเป็นที่น่าสนใจที่จะได้รับ 25 upvotes เมื่อคำถามรูปแบบอื่น ๆ ที่คล้ายกันจะได้รับ 3 หรือ 4 downvotes ทันทีไม่ประชุมดังนั้น "มาตรฐาน" (อาจจะแท็กจาวาสคริปต์มีการรวบรวมข้อมูลโดยคนเมตตา :)
เบน

22
ส่วนใหญ่เราเพิ่งใหม่และตื่นเต้นกับธุรกิจ "ไฟล์" ทั้งหมดหลังจากเบราว์เซอร์เป็นปกติ
Erik Reppen

3
คำตอบเดียวที่ถูกต้องบนหน้าเป็นอย่างใดอย่างหนึ่ง ไม่มีคำตอบอื่นใดให้คัดลอกไฟล์ ไฟล์ใน MacOS และ Windows มีข้อมูลเมตาอื่น ๆ ที่สูญหายโดยเพียงแค่คัดลอกไบต์ ตัวอย่างของข้อมูลที่ไม่ได้คัดลอกคำตอบอื่น ๆ ในหน้านี้หน้าต่างและMacOS แม้คำตอบอื่น ๆ ของ Unix จะไม่คัดลอกวันที่สร้างสิ่งที่มักจะสำคัญเมื่อคัดลอกไฟล์
gman

คำตอบ:


717

นี่เป็นวิธีที่ดีในการคัดลอกไฟล์ในโค้ดหนึ่งบรรทัดโดยใช้สตรีม:

var fs = require('fs');

fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log'));

ในโหนด v8.5.0, copyFile ถูกเพิ่ม

const fs = require('fs');

// destination.txt will be created or overwritten by default.
fs.copyFile('source.txt', 'destination.txt', (err) => {
  if (err) throw err;
  console.log('source.txt was copied to destination.txt');
});

64
เพียงจำไว้ว่าในชีวิตจริงคุณต้องการที่จะตรวจสอบทั้งในcreateReadStreamและcreateWriteStreamสำหรับข้อผิดพลาดดังนั้นคุณจะไม่ได้รับหนึ่งซับ (แม้ว่ามันจะยังคงเป็นเช่นเดียวกับที่รวดเร็ว)
ebohlman

18
มันเร็วกว่า / ช้ากว่าการรัน raw cp test.log newLog.logผ่านมากrequire('child_process').execแค่ไหน?
แลนซ์พอลลาร์ด

41
ดีcopyไม่ได้เป็นแบบพกพาบนหน้าต่างตรงกันข้ามกับวิธีการแก้ปัญหา Node.js เต็ม
Jean

12
child_process.execFile('/bin/cp', ['--no-target-directory', source, target])แต่น่าเสียดายที่ในระบบของฉันโดยใช้กระแสเป็นอย่างมากช้าเมื่อเทียบกับ
Robert

12
ฉันใช้วิธีนี้และทั้งหมดที่ฉันได้รับคือไฟล์เปล่าเมื่อเขียน ความคิดใด ๆ ว่าทำไม? fs.createReadStream('./init/xxx.json').pipe(fs.createWriteStream('xxx.json'));
Timmerz

293

กลไกเดียวกัน แต่เพิ่มการจัดการข้อผิดพลาด:

function copyFile(source, target, cb) {
  var cbCalled = false;

  var rd = fs.createReadStream(source);
  rd.on("error", function(err) {
    done(err);
  });
  var wr = fs.createWriteStream(target);
  wr.on("error", function(err) {
    done(err);
  });
  wr.on("close", function(ex) {
    done();
  });
  rd.pipe(wr);

  function done(err) {
    if (!cbCalled) {
      cb(err);
      cbCalled = true;
    }
  }
}

5
เป็นที่น่าสังเกตว่าจำเป็นต้องมีการตั้งค่าสถานะ cbCalled เนื่องจากข้อผิดพลาดไปป์ทริกเกอร์ข้อผิดพลาดในกระแสข้อมูลทั้งสอง สตรีมต้นทางและปลายทาง
Gaston Sanchez

4
คุณจะจัดการกับข้อผิดพลาดได้อย่างไรถ้าไฟล์ต้นฉบับไม่มีอยู่? ไฟล์ปลายทางยังคงถูกสร้างขึ้นในกรณีนั้น
Michel Hua

1
ฉันคิดว่าข้อผิดพลาดในการWriteStreamจะ unpipe เท่านั้น คุณจะต้องโทรหาrd.destroy()ตัวเอง อย่างน้อยนั่นคือสิ่งที่เกิดขึ้นกับฉัน น่าเศร้าที่มีเอกสารไม่มากยกเว้นจากซอร์สโค้ด
Robert

สิ่งที่cbยืนสำหรับ เราควรผ่านอะไรเป็นอาร์กิวเมนต์ที่สาม
SaiyanGirl

4
@SaiyanGirl 'cb' ย่อมาจาก "callback" คุณควรผ่านฟังก์ชั่น
Brian J. Miller

143

ฉันไม่สามารถรับcreateReadStream/createWriteStreamวิธีการทำงานด้วยเหตุผลบางอย่าง แต่ใช้fs-extraโมดูล npm มันทำงานได้ทันที ฉันไม่แน่ใจในความแตกต่างของประสิทธิภาพการทำงาน

FS-พิเศษ

npm install --save fs-extra

var fs = require('fs-extra');

fs.copySync(path.resolve(__dirname,'./init/xxx.json'), 'xxx.json');

3
นี่คือตัวเลือกที่ดีที่สุดตอนนี้
Zain Rizvi

11
การใช้รหัสซิงโครนัสในโหนดจะฆ่าประสิทธิภาพแอปพลิเคชันของคุณ
mvillar

3
โอ้โปรด ... คำถามนี้เกี่ยวกับวิธีที่เร็วที่สุดในการคัดลอกไฟล์ ในขณะที่เร็วที่สุดมักจะเป็นอัตนัยฉันไม่คิดว่าชิ้นส่วนรหัสแบบซิงโครนัสมีธุรกิจใด ๆ อยู่ที่นี่
sampathsris

24
เร็วที่สุดที่จะใช้หรือเร็วที่สุดในการดำเนินการ? ลำดับความสำคัญที่แตกต่างกันหมายความว่านี่เป็นคำตอบที่ถูกต้อง
Patrick Gunderson

14
fs-extra ยังมีวิธีการแบบอะซิงโครนัสเช่นfs.copy(src, dst, callback);และสิ่งเหล่านี้ควรแก้ไขข้อกังวลของ @ mvillar
Marc Durdin

134

ตั้งแต่ Node.js 8.5.0 เรามีใหม่fs.copyFileและfs.copyFileSyncวิธี

ตัวอย่างการใช้งาน:

var fs = require('fs');

// destination.txt will be created or overwritten by default.
fs.copyFile('source.txt', 'destination.txt', (err) => {
    if (err) throw err;
    console.log('source.txt was copied to destination.txt');
});

2
นี่เป็นคำตอบเดียวที่ถูกต้องในหน้านี้ ไม่มีคำตอบอื่นใดให้คัดลอกไฟล์ ไฟล์ใน MacOS และ Windows มีข้อมูลเมตาอื่น ๆ ที่สูญหายโดยเพียงแค่คัดลอกไบต์ ตัวอย่างของข้อมูลที่ไม่ได้คัดลอกคำตอบอื่น ๆ ในหน้านี้หน้าต่างและMacOS แม้ใน Unix คำตอบอื่น ๆ ก็ไม่ได้คัดลอกวันที่สร้างสิ่งที่มักจะสำคัญเมื่อคัดลอกไฟล์
gman

น่าเศร้าที่นี่ไม่สามารถคัดลอกทุกอย่างใน mac หวังว่าพวกเขาจะแก้ไขได้: github.com/nodejs/node/issues/30575
gman

โปรดทราบว่า BTW copyFile()จะบั๊กขณะเขียนทับไฟล์ที่ยาวกว่า ความอนุเคราะห์uv_fs_copyfile()จนถึงโหนด v8.7.0 (libuv 1.15.0) ดูgithub.com/libuv/libuv/pull/1552
Anton Rudeshko

74

รวดเร็วในการเขียนและใช้งานง่ายพร้อมสัญญาและการจัดการข้อผิดพลาด

function copyFile(source, target) {
  var rd = fs.createReadStream(source);
  var wr = fs.createWriteStream(target);
  return new Promise(function(resolve, reject) {
    rd.on('error', reject);
    wr.on('error', reject);
    wr.on('finish', resolve);
    rd.pipe(wr);
  }).catch(function(error) {
    rd.destroy();
    wr.end();
    throw error;
  });
}

เหมือนกับ async / await syntax:

async function copyFile(source, target) {
  var rd = fs.createReadStream(source);
  var wr = fs.createWriteStream(target);
  try {
    return await new Promise(function(resolve, reject) {
      rd.on('error', reject);
      wr.on('error', reject);
      wr.on('finish', resolve);
      rd.pipe(wr);
    });
  } catch (error) {
    rd.destroy();
    wr.end();
    throw error;
  }
}

1
จะเกิดอะไรขึ้นเมื่อไม่มีอินพุตเพิ่มเติม (การแบ่งเครือข่ายที่ใช้งานไม่ได้) แต่การเขียนยังคงสำเร็จ ทั้งสองจะปฏิเสธ (จากการอ่าน) และแก้ไข (จากการเขียน) ที่ถูกเรียก จะเกิดอะไรขึ้นถ้าทั้งการอ่าน / เขียนล้มเหลว (เซ็กเตอร์ดิสก์ที่ไม่ดีระหว่างการอ่านดิสก์เต็มในระหว่างการเขียน)? จากนั้นปฏิเสธจะถูกเรียกสองครั้ง โซลูชันสัญญาตามคำตอบของไมค์ที่มีธง (น่าเสียดาย) ดูเหมือนจะเป็นทางออกเดียวที่ทำงานได้ซึ่งพิจารณาการจัดการข้อผิดพลาดอย่างเหมาะสม
Lekensteyn

สัญญาจะได้รับการแก้ไขเมื่อการคัดลอกสำเร็จ หากมันถูกปฏิเสธสถานะของมันจะถูกตัดสินและการโทรปฏิเสธหลายครั้งจะไม่สร้างความแตกต่าง
benweet

2
ฉันเพิ่งทดสอบnew Promise(function(resolve, reject) { resolve(1); resolve(2); reject(3); reject(4); console.log("DONE"); }).then(console.log.bind(console), function(e){console.log("E", e);});และค้นหาข้อมูลจำเพาะเกี่ยวกับสิ่งนี้และคุณพูดถูก: การพยายามแก้ไขหรือปฏิเสธสัญญาที่แก้ไขแล้วจะไม่มีผลใด ๆ บางทีคุณอาจขยายคำตอบของคุณและอธิบายว่าทำไมคุณจึงเขียนฟังก์ชันด้วยวิธีนี้ ขอบคุณ :-)
Lekensteyn

2
โดยวิธีการที่closeควรจะเป็นfinishสำหรับสตรีมแบบเขียนได้
Lekensteyn

และถ้าคุณสงสัยว่าทำไมแอปพลิเคชันของคุณไม่ปิดหลังจากข้อผิดพลาดของไปป์/dev/stdinนั่นคือข้อผิดพลาดgithub.com/joyent/node/issues/25375
Lekensteyn

43

ปกติแล้วมันเป็นการดีที่จะหลีกเลี่ยงการทำงานของไฟล์แบบอะซิงโครนัส นี่คือตัวอย่างการซิงค์สั้น ๆ (เช่นไม่มีข้อผิดพลาด):

var fs = require('fs');
fs.writeFileSync(targetFile, fs.readFileSync(sourceFile));

8
โดยทั่วไปแล้วจะเป็นเท็จอย่างยิ่งโดยเฉพาะอย่างยิ่งเนื่องจากมันนำไปสู่การที่คน slurping ไฟล์สำหรับทุกการร้องขอไปยังเซิร์ฟเวอร์ของพวกเขา สิ่งนี้อาจมีราคาแพง
Catalyst

8
การใช้*Syncวิธีการทั้งหมดนั้นขัดกับปรัชญาของ nodejs! ฉันยังคิดว่าพวกเขาจะถูกเลิกช้า แนวคิดทั้งหมดของ nodejs คือมันเป็นเธรดเดี่ยวและเป็นตัวขับเคลื่อนเหตุการณ์
gillyb

11
@gillyb เหตุผลเดียวที่ฉันคิดว่าจะใช้มันเพื่อความเรียบง่าย - ถ้าคุณเขียนสคริปต์สั้น ๆ ที่คุณจะใช้เพียงครั้งเดียวคุณอาจจะไม่สนใจเรื่องการบล็อกกระบวนการเลย
starbeamrainbowlabs

13
ฉันไม่ทราบว่าพวกเขาถูกคัดค้าน วิธีการซิงค์มักจะเป็นความคิดที่แย่มากบนเว็บเซิร์ฟเวอร์ แต่บางครั้งก็เหมาะในบางอย่างเช่น node-webkit ซึ่งมันจะล็อคแอ็คชั่นในหน้าต่างขณะที่คัดลอกไฟล์ โยน gif ที่โหลดและอาจเป็นแถบโหลดที่อัปเดต ณ จุดที่แน่นอนและให้วิธีการซิงค์บล็อกการกระทำทั้งหมดจนกว่าการคัดลอกเสร็จ มันไม่ได้เป็นวิธีปฏิบัติที่ดีที่สุดเท่าที่พวกเขามีสถานที่และเวลา
Erik Reppen

6
วิธีการซิงค์นั้นใช้ได้เมื่อคุณโต้ตอบกับการดำเนินการซิงค์อื่นหรือสิ่งที่คุณต้องการคือการดำเนินการตามลำดับ (เช่นคุณจะทำการจำลองการซิงค์อยู่ดี) หากการดำเนินการเป็นลำดับเพียงหลีกเลี่ยงนรกโทรกลับ (และ / หรือสัญญาซุป) และใช้วิธีการซิงค์ โดยทั่วไปแล้วควรใช้ด้วยความระมัดระวังบนเซิร์ฟเวอร์ แต่ใช้ได้ดีสำหรับกรณีส่วนใหญ่ที่เกี่ยวข้องกับสคริปต์ CLI
srcspider

18

วิธีการแก้ปัญหาของ Mike Schilling พร้อมข้อผิดพลาดสั้น ๆ สำหรับตัวจัดการเหตุการณ์ข้อผิดพลาด

function copyFile(source, target, cb) {
  var cbCalled = false;

  var rd = fs.createReadStream(source);
  rd.on("error", done);

  var wr = fs.createWriteStream(target);
  wr.on("error", done);
  wr.on("close", function(ex) {
    done();
  });
  rd.pipe(wr);

  function done(err) {
    if (!cbCalled) {
      cb(err);
      cbCalled = true;
    }
  }
}

18

หากคุณไม่สนใจว่ามันเป็นแบบอะซิงโครนัสและไม่ได้คัดลอกไฟล์ขนาดกิกะไบต์และไม่ต้องการเพิ่มการพึ่งพาอื่นเพียงเพื่อฟังก์ชั่นเดียว:

function copySync(src, dest) {
  var data = fs.readFileSync(src);
  fs.writeFileSync(dest, data);
}

4
ฉันชอบคำตอบนี้ ชัดเจนและเรียบง่าย
Rob Gleeson

7
@RobGleeson และต้องการหน่วยความจำมากที่สุดเท่าที่เนื้อหาของไฟล์ ... ฉันประหลาดใจโดยนับ upvotes ที่นั่น
Konstantin

ฉันได้เพิ่มข้อแม้ "และไม่ได้คัดลอกไฟล์ขนาดกิกะไบต์"
Andrew Childs

fs.existsSyncโทรควรถูกมองข้าม ไฟล์อาจหายไปในช่วงเวลาระหว่างการfs.existsSyncโทรและการfs.readFileSyncโทรซึ่งหมายความว่าการfs.existsSyncโทรไม่ได้ป้องกันเราจากสิ่งใด
qntm

นอกจากนี้การส่งคืนfalseหากความfs.existsSyncล้มเหลวนั้นเป็นไปตามหลักสรีรศาสตร์ที่ไม่ดีนักเนื่องจากมีผู้บริโภคจำนวนน้อยที่copySyncคิดว่าจะตรวจสอบค่าตอบแทนด้วยตนเองทุกครั้งที่มีการเรียกfs.writeFileSync ใช้ . การโยนข้อยกเว้นเป็นที่นิยมกว่า
qntm

2
   const fs = require("fs");
   fs.copyFileSync("filepath1", "filepath2"); //fs.copyFileSync("file1.txt", "file2.txt");

นี่คือสิ่งที่ฉันใช้เพื่อคัดลอกไฟล์และแทนที่ไฟล์อื่นโดยใช้ node.js :)


1
นี่ไม่ได้ตอบคำถามซึ่งเกี่ยวกับวิธีการคัดลอกไฟล์อย่างมีประสิทธิภาพในแอปพลิเคชันที่ใช้งานหนัก
Jared Smith

@ JaredSmith True แต่การค้นหา google ของฉันทำให้ฉันอยู่ที่นี่และนี่คือสิ่งที่ฉันต้องการ
codepleb

1

สำหรับการคัดลอกที่รวดเร็วคุณควรใช้การfs.constants.COPYFILE_FICLONEตั้งค่าสถานะ อนุญาตให้ (สำหรับระบบไฟล์ที่สนับสนุนสิ่งนี้) ไม่คัดลอกเนื้อหาของไฟล์ มีเพียงรายการไฟล์ใหม่ที่ถูกสร้าง แต่จะชี้ไปที่Copy-on-Write "โคลน"ของไฟล์ต้นฉบับ

ที่จะไม่ทำอะไรเลย / น้อยลงเป็นวิธีที่เร็วที่สุดในการทำอะไรบางอย่าง;)

https://nodejs.org/api/fs.html#fs_fs_copyfile_src_dest_flags_callback

let fs = require("fs");

fs.copyFile(
  "source.txt",
  "destination.txt",
  fs.constants.COPYFILE_FICLONE,
  (err) => {
    if (err) {
      // TODO: handle error
      console.log("error");
    }
    console.log("success");
  }
);

ใช้สัญญาแทน:

let fs = require("fs");
let util = require("util");
let copyFile = util.promisify(fs.copyFile);


copyFile(
  "source.txt",
  "destination.txt",
  fs.constants.COPYFILE_FICLONE
)
  .catch(() => console.log("error"))
  .then(() => console.log("success"));

fs.promises.copyFile
gman

0

โซลูชันของ benweet ตรวจสอบการมองเห็นไฟล์ก่อนคัดลอก:

function copy(from, to) {
    return new Promise(function (resolve, reject) {
        fs.access(from, fs.F_OK, function (error) {
            if (error) {
                reject(error);
            } else {
                var inputStream = fs.createReadStream(from);
                var outputStream = fs.createWriteStream(to);

                function rejectCleanup(error) {
                    inputStream.destroy();
                    outputStream.end();
                    reject(error);
                }

                inputStream.on('error', rejectCleanup);
                outputStream.on('error', rejectCleanup);

                outputStream.on('finish', resolve);

                inputStream.pipe(outputStream);
            }
        });
    });
}

0

ทำไมไม่ใช้ฟังก์ชั่นการสร้างสำเนา nodejs?

มันให้ทั้งรุ่น async และ sync:

const fs = require('fs');

// destination.txt will be created or overwritten by default.
fs.copyFile('source.txt', 'destination.txt', (err) => {
  if (err) throw err;
  console.log('source.txt was copied to destination.txt');
});

https://nodejs.org/api/fs.html#fs_fs_copyfilesync_src_dest_flags


3
ไม่ต้องอัปโหลดเพราะคำตอบนี้ซ้ำซ้อน
Qwertie

-1

ทางออกของไมค์แต่ด้วยสัญญา:

const FileSystem = require('fs');

exports.copyFile = function copyFile(source, target) {
    return new Promise((resolve,reject) => {
        const rd = FileSystem.createReadStream(source);
        rd.on('error', err => reject(err));
        const wr = FileSystem.createWriteStream(target);
        wr.on('error', err => reject(err));
        wr.on('close', () => resolve());
        rd.pipe(wr);
    });
};

@Royi เพราะฉันต้องการโซลูชัน async ... ?
mpen

-1

ปรับปรุงคำตอบอีกข้อหนึ่ง

คุณสมบัติ:

  • หากไม่มีโฟลเดอร์ dst โฟลเดอร์จะสร้างขึ้นโดยอัตโนมัติ คำตอบอื่น ๆ จะทำให้เกิดข้อผิดพลาดเท่านั้น
  • ส่งคืนpromiseซึ่งทำให้ง่ายต่อการใช้ในโครงการขนาดใหญ่
  • ช่วยให้คุณสามารถคัดลอกหลายไฟล์และสัญญาจะทำเมื่อพวกเขาทั้งหมดจะถูกคัดลอก

การใช้งาน:

var onePromise = copyFilePromise("src.txt", "dst.txt");
var anotherPromise = copyMultiFilePromise(new Array(new Array("src1.txt", "dst1.txt"), new Array("src2.txt", "dst2.txt")));

รหัส:

function copyFile(source, target, cb) {
    console.log("CopyFile", source, target);

    var ensureDirectoryExistence = function (filePath) {
        var dirname = path.dirname(filePath);
        if (fs.existsSync(dirname)) {
            return true;
        }
        ensureDirectoryExistence(dirname);
        fs.mkdirSync(dirname);
    }
    ensureDirectoryExistence(target);

    var cbCalled = false;
    var rd = fs.createReadStream(source);
    rd.on("error", function (err) {
        done(err);
    });
    var wr = fs.createWriteStream(target);
    wr.on("error", function (err) {
        done(err);
    });
    wr.on("close", function (ex) {
        done();
    });
    rd.pipe(wr);
    function done(err) {
        if (!cbCalled) {
            cb(err);
            cbCalled = true;
        }
    }
}

function copyFilePromise(source, target) {
    return new Promise(function (accept, reject) {
        copyFile(source, target, function (data) {
            if (data === undefined) {
                accept();
            } else {
                reject(data);
            }
        });
    });
}

function copyMultiFilePromise(srcTgtPairArr) {
    var copyFilePromiseArr = new Array();
    srcTgtPairArr.forEach(function (srcTgtPair) {
        copyFilePromiseArr.push(copyFilePromise(srcTgtPair[0], srcTgtPair[1]));
    });
    return Promise.all(copyFilePromiseArr);
}

-2

คำตอบทั้งหมดข้างต้นที่ไม่ได้ตรวจสอบว่าไฟล์ต้นฉบับนั้นมีอันตรายหรือไม่ ...

fs.stat(source, function(err,stat) { if (err) { reject(err) }

มิฉะนั้นจะมีความเสี่ยงในสถานการณ์ในกรณีที่แหล่งที่มาและเป้าหมายถูกแทนที่ด้วยความผิดพลาดข้อมูลของคุณจะหายไปอย่างถาวรโดยไม่สังเกตเห็นข้อผิดพลาดใด ๆ


นี่เป็นเงื่อนไขการแข่งขัน: ไฟล์อาจถูกทำลายระหว่างการเขียนและอ่าน / เขียน / คัดลอก เป็นการดีกว่าเสมอที่จะลองดำเนินการและจัดการกับข้อผิดพลาดที่เกิดขึ้น
Jared Smith

การตรวจสอบการมีอยู่ของเป้าหมายก่อนที่จะดำเนินการเขียนเพื่อให้แน่ใจว่าคุณไม่ได้เขียนทับเป้าหมายโดยไม่ได้ตั้งใจเช่นครอบคลุมสถานการณ์ที่ปลายทางและแหล่งที่มาถูกกำหนดโดยผู้ใช้โดยผิดพลาดเหมือนกัน ... มันล่าช้าแล้ว whover ให้ฉัน (-1) โปรดตรวจสอบการจัดอันดับของคุณเมื่อเหตุการณ์นี้เกิดขึ้นในโครงการของคุณ :-) อีกครั้ง การแข่งขัน - บนไซต์ที่มีการจราจรหนาแน่นขอแนะนำเสมอว่าจะต้องมีกระบวนการดำเนินการหนึ่งกระบวนการที่ต้องมีการรับประกันการซิงค์ - ใช่แล้วจึงเป็นปัญหาคอขวดของประสิทธิภาพการทำงาน
stancikcom

ฉันไม่ได้ลงคะแนนเพราะคุณผิดฉันลงคะแนนเพราะนี่ไม่ใช่คำตอบสำหรับคำถาม ควรแสดงความคิดเห็นอย่างระมัดระวังเกี่ยวกับคำตอบที่มีอยู่
Jared Smith

ดี - คุณถูกต้องเช่นแอนดรูแก้ปัญหาลูก (กับ 18 upvotes) จะหมดทรัพยากรบนเซิร์ฟเวอร์ / ไฟล์ขนาดใหญ่ ... ฉันจะเขียนความคิดเห็นกับเขา แต่ฉันไม่มีชื่อเสียงที่จะแสดงความคิดเห็น - ดังนั้นคุณได้เห็นโพสต์แบบสแตนด์อโลนของฉัน ... แต่ Jared การปรับลดรุ่นของคุณหมายถึงเส้นทางที่เรียบง่ายสำหรับฉัน - เก็บเงียบและปล่อยให้คนเขียนและแบ่งปันรหัสอันตรายที่ส่วนใหญ่ "งาน" ...
stancikcom

ฉันเข้าใจแล้วไม่มีใครชอบข้อเสนอแนะเชิงลบ แต่มันเป็นเพียง downvote ฉันยืนด้วยเหตุผลที่ให้มันเนื่องจากนี่ไม่ได้ตอบคำถามที่ OP ถามและสั้นพอที่จะแสดงความคิดเห็น คุณสามารถใช้มันได้ตามที่คุณต้องการ แต่ถ้าคุณแยกแยะสิ่งนั้นออกจากสัดส่วนคุณจะพบว่าสแต็คล้นเป็นประสบการณ์ที่น่าผิดหวังมาก
Jared Smith
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.