|
package com.qikux.utils;$ Q3 N6 c) |1 o d# x# |* p
8 }" M' f7 d# _2 H& T$ G4 y0 fimport java.io.*;6 j* q" q L1 B& M$ a
import java.nio.charset.StandardCharsets;
$ i; N2 o, v( ?9 X4 b2 Bimport java.util.ArrayList;7 e r/ ? i2 ~1 P+ |! T
import java.util.List;
, _( @( m8 v! Y! M& Cimport java.util.Map;/ l3 ~1 E. g x
import java.util.StringJoiner;. Y# b6 i& P' H# r9 m; r, h
import java.util.concurrent.ConcurrentHashMap;
# |) M$ W0 U0 G* v. S. [: Z4 F- L/ _, |- c4 x! O# n9 e
public class FileUtils {- R) n/ U) B1 b/ @) O( m
/**1 A' c) y* A/ y( E0 T/ V
* 支持断点续传
, |$ W* i2 t* \+ Q& F* I9 n: R * @src 拷贝的原文件* Z& W' S: s' q9 H# e: i9 F
* @desc 拷贝的位置) j0 ^+ n C: {; p- G: k
* @threadNum 开启的线程数- _1 h3 f9 I4 b
*/8 x4 e1 V: b- q& ~9 Y
public static void transportFile(File src, File desc, int threadNum) throws Exception {" R5 q2 x- A1 A- V) t
// 每一个线程读取的大小
+ w$ K, R& ~6 t int part = (int)Math.ceil(src.length() / threadNum);! d9 b* G, ~ n3 H; C
// 存储多个线程、用于阻塞主线程, e2 X J0 E1 m3 t0 i+ A7 ]/ x
List list = new ArrayList();
I& j8 |9 X, L5 E8 w
" i" q9 [3 ?$ v) i- z. f // 定义一个基于多线程 的 hashmap' r" M+ {5 W& o/ _
final Map map = new ConcurrentHashMap();
2 X5 A& x0 d3 @' K8 l5 n* z // 读取 日志文件中的数据
9 b! N% G! U3 \, a String[] $data = null ;6 R: } O" S/ C" `( B
$ h5 z' s. `* a0 @% ]: M String logName = desc.getCanonicalPath() + ".log";7 i+ l5 D) Q( W; T( [) F& K
. K+ B* E: m; t7 e1 n File fl = new File(logName);
, p% ~1 F- g+ ]0 S4 j- T- ]" b' c* ~5 d" z) u/ T% @& I# e
if (fl.exists()) {
8 w' | w! Z1 E; z7 G" }3 ^! T BufferedReader reader = new BufferedReader(new FileReader(fl)); ~: t" K! B- Q* i; V; t
String data = reader.readLine();
% `- p' C2 p. T1 P% Q& A2 ` // 拆分 字符串6 P; V. ?' I3 M5 s
$data = data.split(",");3 Q3 P7 C: p1 T
reader.close();3 a, J2 _0 v w- O
}
2 z- ~2 b$ i( F, d6 d! ^' H5 r! P# \" I- u0 m3 B
final String[] _data = $data ;2 S$ o: y- J6 H4 g$ ~! R3 A4 L
7 H0 I1 z/ ]0 I$ e2 d$ A for (int i = 0; i < threadNum; i++) {
7 u3 L) a! j% k) ? final int k = i ;8 q9 ^ |5 E9 g& I; S: f. r
Thread thread = new Thread(() -> {
2 v4 s: s6 u, b6 m // 线程具体要做的事情
" w- p! X. r) u- R RandomAccessFile log = null ;6 m% o' `/ O6 W1 L* ^
try {
9 U6 P4 \) @3 N9 F% c) S& ~ RandomAccessFile in = new RandomAccessFile(src, "r");( Y* i" h+ O6 Z9 {* g
RandomAccessFile out = new RandomAccessFile(desc, "rw");
; f% h. g8 q; W: t* x: }7 W# S
. H' ~4 F2 h6 j0 G4 C2 M2 j log = new RandomAccessFile(logName, "rw");
: _2 W! a' Z# N( Q* k% o& j // 从指定位置读) `: b& Z% a# N# L X B5 @
in.seek(_data ==null ?k * part : Integer.parseInt(_data[k]) );
& e2 S/ i* ~- S# p+ p# T2 N out.seek(_data ==null ?k * part : Integer.parseInt(_data[k]) );
7 c- P6 u8 C1 x4 e6 {+ K4 E
4 G6 i2 {2 g" t( s% X4 R byte[] bytes = new byte[1024 * 2];0 Y( A( A" W' l; G# Q
int len = -1, plen = 0;
' P' O6 _1 M4 d3 N/ t7 I, V% k& w1 p% a( B/ X4 j' E5 y; T; x( s
while (true) {7 v9 f. u/ t9 y# z, d1 k7 v
len = in.read(bytes);
' ?* r) T* S% ?/ C8 Q- z8 F4 K( v5 c, O9 }0 d5 }+ X8 d
if (len == -1) {
3 V) p( m4 Y+ f H8 Y, P break;5 A) P8 V A9 ^" l
}) Q( U" k. J! X ]* i @
// 如果不等于 -1 , 则 累加求和6 f7 d) i& _5 [7 h
plen += len;
* g: u& V. n" Q, s! X
, M$ H% Q: G2 e" A5 E // 将读取的字节数,放入 到 map 中' S2 D3 J. u; z! d7 y k4 c, X
map.put(k, plen + (_data ==null ?k * part : Integer.parseInt(_data[k])) );
4 R' I: v8 `. Q! y0 ]: p
: u3 o q% N7 {, i- K // 将读取到的数据、进行写入
0 ~) ^4 C5 V) ^" w" P. H! P8 K out.write(bytes, 0, len);
3 g0 w8 J, q6 p, f5 _/ a0 ~9 a R // 将 map 中的数据进行写入文件中* v2 @+ E$ x/ _) |( W4 |9 q X* B
log.seek(0); // 直接覆盖全部文件 z, N6 }9 Q5 p5 ?& `+ c# X
StringJoiner joiner = new StringJoiner(",");5 s- f# B; K8 ^. G/ \+ |: f1 q6 q
map.forEach((key, val)-> joiner.add(String.valueOf(val)));' y) T; d% y- K* i
log.write(joiner.toString().getBytes(StandardCharsets.UTF_8));
$ K2 U+ _) w0 b2 p8 W8 G' j N2 v1 z, p n
if (plen + (_data ==null ? k * part : Integer.parseInt(_data[k])) >= (k+1) * part ) {8 E! w4 U s# I$ M: |* Y8 ^; k
break;0 _. c/ G# C2 j: P
}
9 x3 c$ c( a% a' o! B. { }& t2 N$ B# Q: ?. A6 q7 |. o# w
} catch (Exception e) {1 D5 ~" C; [/ j+ y1 [5 V
e.printStackTrace();
4 j$ }0 D" l" }4 k8 `- [ }finally {
) }1 F! i* G: o( B3 i7 v/ M try {
% S0 F) |! g; A" M) O4 W3 F$ } if (log !=null) log.close();% N/ M( e* t0 \& ]+ I/ ^
} catch (IOException e) {
3 o& U2 x2 e3 b0 {3 Y& s3 \* Z6 ] e.printStackTrace();" G+ r h5 c9 u- U& |3 i0 w1 N1 w
}
' W" Q$ c1 \9 c% {% N# e }
0 i' J. |* d8 z) b. u) e8 T$ `" ~5 d3 \3 p, G, ^& p6 D
});' W n6 u" r8 n( ?& q A
thread.start();1 w; }% N& v, y! u- F# a
// 把这5个线程保存到集合中
0 d1 n# R; ~: d1 L- ~( W list.add(thread);
; r- H3 S7 _4 D7 a }
( J1 h+ ]% G( W, K% j+ M for(Thread t : list) {
* `+ c( E# c: @: p3 D t.join(); // 将线程加入,并阻塞主线程
) N) L: ?1 s/ x6 b/ S5 u* ? }
* \2 d4 A$ z3 O1 h0 _* T // 读取完成后、将日志文件删除即可
" b. O7 |' I8 q% |) d4 F3 @' W H$ N new File(logName).delete();
* T( {: N( H& @) W/ e& \% c' ] }
& m8 Y# _5 x0 n2 u, Q/ `3 @% g, T" ]0 }+ }. r
/**$ h. |( @# y1 T. [
* 支持断点续传2 I" ?0 ~* z: g* [# R
* @src 拷贝的原文件
) M9 A# _: V! m) _ * @desc 拷贝的位置 ~6 Q' u9 c0 M0 a. X7 \
*/0 f+ O5 M4 v: O; R: G; Y
public static void transportFile(File src, File desc) throws Exception {
4 x% P9 k# t/ l* G- a8 R6 ` transportFile(src, desc, 5);
" ^6 F. g. n+ ~7 c3 G3 ?" ` }
# E$ A4 l+ W$ P& ^ S7 M0 w" p: T7 Q* {: ?
public static void transportFile(String src, String desc) throws Exception {
5 q4 U9 J2 u) C: c* Q2 U8 J! c transportFile(new File(src), new File(desc));, L/ i9 ]% K* p9 w) L
}
. Z5 j4 q) D* f, c4 Q% G}& m0 @$ N9 v) U
2 d+ B o% k- p9 j- B& f% X& N/ L0 r
资源下载地址和密码(百度云盘): [/hide] 百度网盘信息回帖可见
4 y0 u& O3 {5 y# E: W! w8 O" j- q
% ^6 r4 P! O G5 R: f8 K
& I* ~! ?# m4 z5 ~; z2 q: \! F3 u6 z7 x3 k8 h: g- K
本资源由Java自学网收集整理【www.javazx.com】 |
|